使用slots
如果想要限制实例的属性,如只允许对Student实例添加
name和age属性;Python允许在定义class的时候,定义一个特殊的__slots__变量来限制该class实例能添加的属性class Student(object):__slots__ = ('name', 'age') #用tuple定义允许绑定的属性名称
使用
__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的除非在子类中也定义
__slots__,这样子类实例允许定义的属性就是自身的__slots__加上父类的__slots__使用@property
Python内置的
@property装饰器就是负责把一个方法变成属性调用的class Student(object):@propertydef score(self):return self._score@score.setterdef 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
把一个getter方法变成属性,只需要加上
@property就可以,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值属性的方法名不要和实例变量重名,否则会造成无限递归,最终导致栈溢出报错
多重继承
Python允许使用多重继承,
Mixln就是一种常见的设计定义出肉食动物
CarnivorousMixIn和植事动物HerbivoresMixIn,让某个动物同时拥有好几个MixInclass Dog(Mammal, RunnableMixIn, CarnivorousMixIn):pass
定制类
str
打印出来的实例能够容易看出内部重要的数据
class Student(object):def __init__(self, name):self.name = namedef __str__(self):return 'Student object (name: %s)' % self.name#__repr__()是为调试服务的,加上下面这句第8行就可以不写print也能看到打印内容__repr__ = __str__print(Student('Michael')) #Student object (name: Michael)
iter
iter()方法返回一个迭代对象,for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到
StopIteration错误时退出循环class Fib(object):def __init__(self):self.a, self.b = 0, 1 # 初始化两个计数器a,bdef __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 # 返回下一个值
getitem
上面的Fib实例虽然能作用于for循环,但不能把它当成list来使用;若需要能够按照下标取出元素,需要实现
__getitem__()class Fib(object):def __getitem__(self, n):if isinstance(n, int): # n是索引a, b = 1, 1for x in range(n):a, b = b, a + breturn aif isinstance(n, slice): # n是切片start = n.startstop = n.stopif start is None:start = 0a, b = 1, 1L = []for x in range(stop):if x >= start:L.append(a)a, b = b, a + breturn L
与之对应还有
__setitem__(),把对象视作list或dict来对集合赋值。还有一个__delitem__()方法用于删除某个元素getattr
只有在没有找到属性的情况下,才调用
__getattr__,只有在没有找到属性的情况下才调用__getattr__,已有的属性不会在__getattr__中查找任意的调用如
s.abc都会返回None,因为__getattr__默认返回就是None;要让class只相应特定的几个属性,那么就要抛出AttributeErrorcall
任何类都可以通过定义一个
__call__()方法以对实例进行调用能够被调用的对象就是一个
Callable对象,比如函数和带有__call__()的类实例 ```python class Chain(object):def init(self, path=’’):
self._path = path
def getattr(self, path):
return Chain('%s/%s' % (self._path, path))
def str(self):
return self._path
repr = str
Chain().status.user.timeline.list #’/status/user/timeline/list’
<a name="QEnBI"></a>### 使用枚举类- Python提供了`Enum`来为枚举类型定义一个class类型,每个常量都是class的一个唯一实例;`value`属性则是自动赋给成员的`int`常量,默认从`1`开始计数;如果需要更精确地控制枚举类型,可以从`Enum`派生出自定义类,`@unique`装饰器可以检查保证没有重复值```pythonfrom enum import EnumMonth = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))from enum import Enum, unique@uniqueclass Weekday(Enum):Sun = 0 # Sun的value被设定为0Mon = 1Tue = 2Wed = 3Thu = 4Fri = 5Sat = 6
使用元类
type()
type()函数允许动态创建出类来,动态语言本身支持运行期动态创建类;一个class的类型就是type,而一个实例的类型是classtype()函数既可以返回一个对象的类型,又可以创建出新的类型,譬如可以通过type()函数创建出Hello类,而无需通过class Hello(object)...定义def fn(self, name='world'): # 先定义函数print('Hello, %s.' % name)Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
metaclass
比较难,暂时先不管
