在class中定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
class Student(object): __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 s = Student() # 创建新的实例 s.name = 'Michael' # 绑定属性'name' s.score = 99 # 绑定属性'score'-->出错__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
(2). @property的使用在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改,解决方案:
通过set_score设置成绩,在通过get_score获取成绩,在set_score中检查参数(已经讲过)
使用内置的@property装饰器,既可以检查参数,又可以类似属性那样访问类的变量
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。
class Student(object): # @property将get_Score方法变成属性 @property def score(self): return self._score # @score.setter将set_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() s.score = 9999 # error (3). 多重继承MixLn的设计MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系
class Animal(object): pass class Bird(Animal): pass class Parrot(Bird): pass # 此时我们需要加入额外的功能fly # 先定义好fly的类 class Flyable(object): def fly(self): print('Flying...') # 同时继承两个类 class Parrot(Bird, Flyable): pass (4). 定制个性化类 1): __str__ 和 __repr__让打印的object更漂亮:
__str__: 用print打印
__repr__: 直接输入对象名
class Student(object): # 加下划线 def __init__(self, name): self.__name = name def __str__(self): msg = 'Student name is' + self.__name return msg __repr__ = __str__ s = Student() print(s) # 打印出 Student name is..... s # 效果跟上面的一样 2): __iter__将类定义成类似list或者tuple那种,可以用于for循环的作用
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__(self): return self # 实例本身就是迭代对象,故返回自己 def __getitem__(self, n): if isinstance(n, int): # n是索引 a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(n, slice): # n是切片 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 def __next__(self): self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: # 退出循环的条件 raise StopIteration() return self.a # 返回下一个值 for i in Fib(): print(n) # 1,1,2,3,5,.......,75025 # 因为__getitem__的作用,可以index某个值 f = Fib() f[0] # 1 # 也可以切片 print(f[0:5]) # 1,1,2,3,5 3): __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.实例进行直接调用就好比对一个函数进行调用一样,所以你完全可以把对象看成函数,把函数看成对象
4) 枚举类Enum定义常量
from enum import Enum, unique # unique保证没有重复值 @unique class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6 # 访问枚举类 print(Weekday.Mon) # Weekday.Mon print(Weekday.Mon.value) # 1 print(Weekday(1))) # # Weekday.Mon 5) type()动态创建类Classtype()函数既可以返回一个对象的类型,又可以创建出新的类型
type()和Class()的功能是一样的
要创建一个class对象,type()函数依次传入3个参数:
class的名称;
继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。
def fn(self,): # 先定义函数 print("hello", name) Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello classgraph TD; A-->B; A-->C; B-->D; C-->D;