@yanglt7
2018-12-03T07:45:42.000000Z
字数 3334
阅读 713
Python
class Animal(object):passclass Mammal(Animal):passclass Bird(Animal):passclass Dog(Mammal):passclass Bat(Mammal):passclass Parrot(Bird):passclass Ostrich(Bird):passclass Runnable(object):def run(self):print('Running...')class Flyable(object):def fly(self):print('Flying...')class Dog(Mammal,Runnable):passclass Bat(Mammal,Flyable):pass
通过多重继承,一个子类就可以同时获得多个父类的所有功能。
MixIn 的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个 MixIn 的功能,而不是设计多层次的复杂的继承关系
class Dog(Mammal, RunnableMixIn, CarnivorousMixIn):pass
>>> class Student(object):... def __init__(self, name):... self.name = name...>>> print(Student('Michael'))<__main__.Student object at 0x109afb190>
>>> class Student(object):... def __init__(self,name):... self.name=name... def __str__(self):... return 'Student object (name:%s)' % self.name...>>> print(Student('Michael'))Student object (name:Michael)>>> s = Student('Michael')>>> s<__main__.Student object at 0x109afb310>
class Student(object):def __init__(self, name):self.name = namedef __str__(self):return 'Student object (name=%s)' % self.name__repr__ = __str__>>> s=Student('Michael')>>> sStudent object (name=Michael)
如果一个类想被用于 for ... in 循环,类似 list 或 tuple 那样,就必须实现一个 __iter__() 方法,该方法返回一个迭代对象,然后,Python 的 for 循环就会不断调用该迭代对象的 __next__() 方法拿到循环的下一个值,直到遇到 StopIteration 错误时退出循环。
>>> class Fib(object):... def __init__(self):... self.a,self.b=0,1... def __iter__(self):... return self... def __next__(self):... self.a,self.b=self.b,self.a+self.b... if self.a>1000:... raise StopIteration()... return self.a...
>>> for n in Fib():... print(n)...1123581321345589144233377610987
Fib 实例虽然能作用于 for 循环,看起来和 list 有点像,但是,把它当成 list 来使用还是不行,要表现得像 list 那样按照下标取出元素,需要实现 __getitem__() 方法:
>>> class Fib(object):... def __getitem__(self,n):... a,b=1,1... for x in range(n):... a,b=b,a+b... return a...>>> f=Fib()>>> f[0]1
__getitem__() 传入的参数可能是一个 int,也可能是一个切片对象 slice,要做判断才能切片:
>>> class Fib(object):... def __getitem__(self,n):... if isinstance(n,int):... a,b=1,1... for x in range(n):... a,b=b,a+b... return a... if isinstance(n,slice):... start=n.start... stop=n.stop... if start is None:... start=0... a,b=1,1... L=[]... for x in range(stop):... if x>=start:... L.append(a)... a,b=b,a+b... return L...>>> f=Fib()>>> f[0:5][1, 1, 2, 3, 5]
但是没有对 step 参数作处理:
>>> f[:10:2][1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
也没有对负数作处理,所以,要正确实现一个 __getitem__() 还是有很多工作要做的。
此外,如果把对象看成 dict,__getitem__() 的参数也可能是一个可以作 key 的 object,例如 str。
与之对应的是 __setitem__() 方法,把对象视作 list 或 dict 来对集合赋值。最后,还有一个 __delitem__() 方法,用于删除某个元素。
写一个 __getattr__() 方法,动态返回一个属性。
>>> class Student(object):... def __init__(self):... self.name='Michael'... def __getattr__(self,attr):... if attr=='score':... return 99...>>> s=Student()>>> s.name'Michael'>>> s.score99
返回函数也是完全可以的:
>>> class Student(object):... def __getattr__(self,attr):... if attr=='age':... return lambda:25...>>> s=Student()>>> s.age()25
此外,注意到任意调用如 s.abc 都会返回 None,这是因为我们定义的 __getattr__ 默认返回就是 None。要让 class 只响应特定的几个属性,我们就要按照约定,抛出 AttributeError 的错误:
class Student(object):def __getattr__(self,attr):if attr=='age':return lambda:25raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
任何类,只需要定义一个 __call__() 方法,就可以直接对实例进行调用。请看示例:
>>> class Student(object):... def __init__(self,name):... self.name=name... def __call__(self):... print('My name is %s.' % self.name)...>>> s=Student('Michael')>>> s()My name is Michael.
__call__()还可以定义参数。能被调用的对象就是一个Callable对象
>>> callable(max)True>>> callable([1,2,3])False>>> callable(None)False>>> callable('str')False