给实例绑定一个方法:
>>> def set_age(self, age): # 定义一个函数作为实例方法
... self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25
为了给所有实例都绑定方法,可以给class绑定方法:
>>> def set_score(self, score):
... self.score = score
...
>>> Student.set_score = MethodType(set_score, None, Student)
-
使用__slots__
用来限制class可以添加的属性
>>> class Student(object):
... __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
...
使用__slots__要注意,它定义的属性只对当前类起作用,对继承的子类是不起作用的。
除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__。
-
使用@property
Python内置的@property装饰器负责把一个方法变成属性调用。
class Student(object):
@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
'''
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
'''
@property
的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@score.setter
,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:
>>> 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!
-
多重继承
多重继承就是继承多个父类,这样一个子类就可以同时获得多个父类的所有功能。
例如
class Dog(Mammal, Runnable):
pass
Mixin模式
目的是给一个类增加多个功能,在设计类的时候,优先考虑通过多重继承来组合多个Mixin的功能。
__str__()返回一个好看的字符串————改变的是print输出变量
__repr__()改变的事直接显示变量调用,为调试服务
__iter__
如果一个类想被用于for...in循环,类似list或者tuple那样,就必须实现一个__iter__()
方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()
方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
我们以斐波那契数列为例,写一个Fib类,可以作用于for循环:
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己
def next(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration();
return self.a # 返回下一个值
现在,试试把Fib实例作用于for循环:
>>> for n in Fib():
... print n
...
1
1
2
3
5
...
46368
75025
更多定制类翻看博客
-
使用元类
type()和metaclass(元类)
先定义metaclass,就可以创建类,最后创建实例。metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。