1.鸭子类型
动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
对于静态语言(例如Java)来说,如果需要传入Animal
类型,则传入的对象必须是Animal
类型或者它的子类,否则,将无法调用run()
方法。
对于Python这样的动态语言来说,则不一定需要传入Animal
类型。我们只需要保证传入的对象有一个run()
方法就可以了:
例如:Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()
方法,返回其内容。但是,许多对象,只要有read()
方法,都被视为“file-like object“。
许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了read()
方法的对象。
2.获取对象信息
1)获取对象属性,方法 dir()
>>> dir('ABC') ['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
__xxx__方法,一般有特殊用途,eg:__length__
>>> len('ABC') 3 >>> 'ABC'.__len__() 3
#----我们自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法: >>> class MyDog(object): ... def __len__(self): ... return 100 ... >>> dog = MyDog() >>> len(dog) 100
2)hasattr:检测是否存在属性
>>> class MyObject(object): ... def __init__(self): ... self.x = 9 ... def power(self): ... return self.x * self.x ... >>> obj = MyObject() #--------------------------- >>> hasattr(obj, 'x') # 有属性'x'吗? True >>> obj.x 9 >>> hasattr(obj, 'y') # 有属性'y'吗? False
3)getattr和setattr
>>> setattr(obj, 'y', 19) # 设置一个属性'y' >>> hasattr(obj, 'y') # 有属性'y'吗? True >>> getattr(obj, 'y') # 获取属性'y' 19 >>> obj.y # 获取属性'y' 19
#如果试图获取不存在的属性,会抛出AttributeError的错误: >>> getattr(obj, 'z') # 获取属性'z' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'MyObject' object has no attribute 'z' #可以传入一个default参数,如果属性不存在,就返回默认值: >>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404 404 #也可以获得对象的方法: >>> hasattr(obj, 'power') # 有属性'power'吗? True >>> getattr(obj, 'power') # 获取属性'power' <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>> >>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn >>> fn # fn指向obj.power <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>> >>> fn() # 调用fn()与调用obj.power()是一样的 81
3.@property
装饰器
负责把一个方法变成属性调用
使用前
class Student(object): def get_score(self): return self._score def set_score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value #---------------------- >>> s = Student() >>> s.set_score(60) # ok! >>> s.get_score() 60 >>> s.set_score(9999) Traceback (most recent call last): ... ValueError: score must between 0 ~ 100!
使用后
(只定义getter方法,不定义setter方法就是一个只读属性,下例中age是只读属性,birth和score是可读写属性)
class Student(object): @property def age(self): return 2015 - self._birth @property def birth(self): return self._birth @birth.setter def birth(self, value): self._birth = value @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value #---------------------- >>> s = Student() >>> s.score = 60 # OK,实际转化为s.set_score(60) >>> s.score # OK,实际转化为s.get_score() 60 >>> s.score = 9999 Traceback (most recent call last): ... ValueError: score must between 0 ~ 100!
4.多重继承
#设计类 class Animal(object): pass # 大类: class Mammal(Animal): pass class Bird(Animal): pass # 各种动物: #class Dog(Mammal): #pass class Dog(Mammal, Runnable): pass #class Bat(Mammal): #pass class Bat(Mammal, Flyable): pass #class Parrot(Bird): #pass #class Ostrich(Bird): #pass #跑/飞类 class Runnable(object): def run(self): print('Running...') class Flyable(object): def fly(self): print('Flying...')
MixIn
给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。