鸭子是什么类
一、派生与方法重用
Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,新式类内置了mro方法可以查,看线性列表的内容,经典类没有该内置该方法。
子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找。
方式1:指名道姓调用某一个类下的函数—>不依赖继承的关系
class People1: def __init__(self, name, age, gender): self._name = name self._age = age self._gender = gender
def f1(self): print(‘%s say hello to you.’ % self._name)
class Teacher1(People1): def __init__(self, name, age, gender, salary, level): # self._name = name # self._age = age # self._gender = gender People1.__init__(self, name, age, gender) self._salary = salary self._level = level
teacher_obj = Teacher1(‘张三’, 18, ‘male’, 1000, 10)teacher_obj.f1() # 直接调用父类的方法
super()调用父类提供给自己的方法,严格依赖继承关系
super() 此时会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro去当前类的父类中查找属性。 |
class People2: def __init__(self, name, age, gender): self._name = name self._age = age self._gender = gender
def f1(self): print(‘%s say hello to you.’ % self._name)
class Teacher2(People2): def __init__(self, name, age, gender, salary, level): # self.__init__(name, age, gender) # 进入递归了 永远都是找的自身的__init__ # super() 此时会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro去当前类的父类中查找属性 # super(Teacher2, self).__init__(name, age, gender) # python2的用法 super().__init__(name, age, gender) # 调用的是方法,自动传入对象 访问的是父类的__init__方法 self._salary = salary self._level = level
print(Teacher2.mro())teacher_obj = Teacher2(‘李四’, 18, ‘male’, 1000, 10)teacher_obj.f1() # 直接调用父类的方法
方式1是跟继承没有关系的,而方式1的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找。
super()案例
class A: def test(self): print(‘From A’) super().test() # super()参照的是属性发起者的mro进行查找 查找当前类的下一个类是谁
class B: def test(self): print(‘From B’)
class C(A, B): pass
C_obj = C()C_obj.test() # 当前位置没有这个功能属性,然后去A找,A打印出From A –通过super()方法又到B中去找-> From Bprint(C.mro()) # [<class ‘__main__.C’>, <class ‘__main__.A’>, <class ‘__main__.B’>, <class ‘object’>]
二、组合
在一个类中以另外一个类的对象作为数据属性,称为类的组合。
继承是一种“是”的关系,比如老师是人、学生是人,当类之间有很多相同的之处,应该使用继承;而组合则是一种“有”的关系,比如老师有生日,老师有多门课程,当类之间有显著不同,并且较小的类是较大的类所需要的组件时,应该使用组合。 |
class Course: def __init__(self, course_name, course_period, course_price): self._course_name = course_name # 课程名称 self._course_period = course_period # 课程周期 self._course_price = course_price # 课程价格
def tell_course_info(self): print(‘%s – %s – %s’ % (self._course_name, self._course_period, self._course_price))
class BirthDay: def __init__(self, year, month, day): self._year = year self._month = month self._day = day
def tell_birth_info(self): print(‘%s – %s – %s’ % (self._year, self._month, self._day))
class People: def __init__(self, name, age, gender): self._name = name self._age = age self._gender = gender
class Teacher(People): def __init__(self, name, age, gender, year, month, day, salary): super().__init__(name, age, gender) # 重用父类 self._birth = BirthDay(year, month, day) # 调用Birthday()类 组合使用 self._courses = [] # 存储课程的列表 self._salary = salary
def teach(self): print(‘%s is teacher’ % self._name) # 调用的是People()类中的数据属性
cf1 = Course(‘竞技模式’, 30, 100)cf2 = Course(‘团队模式’, 10, 200)teacher = Teacher(‘张三’, 18, ‘male’, 2003, 12, 12, 2000)teacher._courses.append(cf1) # 添加课程teacher._courses.append(cf2)
“””此时对象teacher集对象独有的属性、Teacher类中的内容、Course类中的内容于一身(都可以访问到),是一个高度整合的产物”””
# 重用Birthday类的功能teacher._birth.tell_birth_info() # 打印生日信息
# 重用Course类的功能for obj in teacher._courses: # teacher._courses的列表中添加了两个Course类的实例化对象 obj.tell_course_info()
三、多态与鸭子类型
多态,指的是一种事物多种形态,同时,多态更像是一种思想,用一套统一的标准去运作整个程序或流程,多态性的存在增强了程序的灵活性和可扩展性。如水有多种形态,它可以是冰水、矿泉水、茶水。当你将水倒入杯子,水就变成杯子;当你倒水入茶壶,水就变成茶壶。
Be Water of my friend!
class Animal: # 统一所有子类的方法 def talk(self): print(‘动物的声音~~~~’, self.__class__.__name__, end=’ ‘) # self.__class__.__name__ 获取类名
class People(Animal): def talk(self): super().talk() print(‘哈~~~~’)
class Cat(Animal): def talk(self): super().talk() print(‘喵~~~~’)
class Dog(Animal): def talk(self): super().talk() print(‘汪~~~~’)
# 多态会带来什么样的特性 —> 多态性””” 多态性是指在不考虑对象具体类型的情况下而直接使用对象”””
people = People()cat = Cat()dog = Dog()
people.talk()cat.talk()dog.talk()””” 动物的声音~~~~ People 哈~~~~ 动物的声音~~~~ Cat 喵~~~~ 动物的声音~~~~ Dog 汪~~~~”””
同样,咱们可以定义一个统一接口来调用这个功能
def animal_talk(animal): animal.talk()
animal_talk(people)animal_talk(cat)animal_talk(dog)””” 动物的声音~~~~ People 哈~~~~ 动物的声音~~~~ Cat 喵~~~~ 动物的声音~~~~ Dog 汪~~~~”””
多态性的体现
# 多态性的体现print(‘woshibab’.__len__()) # 能统计字符的长度 8print([1, 2, 3, 4, 5].__len__()) # 5
print()
def func_len(val): return val.__len__() # 返回传入参数的长度
print(func_len([1, 2, 3, 4, 5])) # 5
可以在父类引入抽象类的概念来硬性限制子类必须有某些方法名
import ab
c# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化class Animal1(metaclass=abc.ABCMeta): @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法 def talk(self): # 抽象方法中无需实现具体的功能 pass
class Cat(Animal1): # 但凡继承Animal的子类都必须遵循Animal规定的标准 def talk(self): pass
# obj = Animal1() # 不能实例化抽象类自己cat = Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
鸭子类型
如果有只动物走路像鸭子,游泳像鸭子,叫声也像鸭子,毋庸置疑,那就是鸭子!!!!! |
#二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系class Txt: # Txt类有两个与文件类型同名的方法,即read和write def read(self): pass
def write(self): pass
class Disk: # Disk类也有两个与文件类型同名的方法:read和write def read(self): pass
def write(self): pass
四、绑定方法与非绑定方法
绑定方法
将调用者本身当作第一参数自动传入。
1、绑定给对象的方法 调用者是对象,自动传入的是对象 2、绑定给类的方法 调用者是类,自动传入的是类 |
@classmethod
# 在类中正常定义的函数默认是绑定到对象的,# 而为某个函数加上装饰器@classmethod后,该函数就绑定到了类。
import settings
class Mysql: def __init__(self, host, port): self._host = host self._port = port
def func(self): print(‘%s:%s’ % (self._host, self._port))
@classmethod # 将下面的函数装饰成绑定给类的方法,调用者是类,自动传入的也是类 def from_conf(cls): # 从配置文件中读取配置进行初始化 print(cls) return cls(settings.HOST, settings.PORT)
obj1 = Mysql(‘127.0.0.1’, 3306)obj2 = Mysql(settings.HOST, settings.PORT)# obj3 = Mysql.from_conf # 绑定到类的方法obj3 = Mysql.from_conf() # <class ‘__main__.Mysql’> 调用类方法,自动将类MySQL当作第一个参数传给clsprint(obj3.__dict__) # {‘_host’: ‘127.0.0.1’, ‘_port’: 3306}
#settings中的内容
HOST=’127.0.0.1’PORT=3306
非绑定方法
没有绑定给任何人,调用者可以是类、对象,没有自动传参的效果。
为类中某个函数加上装饰器@staticmethod后,该函数就变成了非绑定方法,也称为静态方法。 该方法不与类或对象绑定,类与对象都可以来调用它,但它就是一个普通函数而已,因而没有自动传值那么一说。 |
class Mysql2: def __init__(self, host, port): self._id = self.create_id() self._host = host self._port = port
@staticmethod # 将下述函数装饰成一个静态的方法 def create_id(): import uuid return uuid.uuid4()
@classmethod def f1(cls): pass
def f2(self): pass
conn=Mysql2(‘127.0.0.1’, 3306)print(conn._id)# print(conn.create_id) # <function Mysql2.create_id at 0x00000000014BB430>
“”” 若类中需要一个功能, 该功能的实现代码中需要引用对象则将其定义成对象方法, 需要引用类则将其定义成类(@classmethod)方法, 无需引用类或对象则将其定义成静态(@staticmethod)方法。
“””
五、一些内置函数的简单介绍
Python内置函数
https://www.runoob.com/python/python-built-in-functions.html
***************************************************************
完