@yanglt7
2018-12-03T07:45:42.000000Z
字数 3334
阅读 638
Python
class Animal(object):
pass
class Mammal(Animal):
pass
class Bird(Animal):
pass
class Dog(Mammal):
pass
class Bat(Mammal):
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...')
class Dog(Mammal,Runnable):
pass
class 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 = name
def __str__(self):
return 'Student object (name=%s)' % self.name
__repr__ = __str__
>>> s=Student('Michael')
>>> s
Student 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)
...
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
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.score
99
返回函数也是完全可以的:
>>> 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:25
raise 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