摘自谬雪峰https://www.liaoxuefeng.com/wiki/1016959663602400/1017501655757856
>>> s = Student()
>>> s.name = ‘Michael‘ # 动态给实例绑定一个属性
>>> def set_age(self, age): # 定义一个函数作为实例方法
... self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25
>>> def set_score(self, score):
... self.score = score
...
>>> Student.set_score = set_score
通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
class Student(object):
__slots__ = (‘name‘, ‘age‘) # 用tuple定义允许绑定的属性名称
>>> s.score = 99 # 绑定属性‘score‘
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: ‘Student‘ object has no attribute ‘score‘
由于‘score‘没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:
class GraduateStudent(Student):
... pass
...g = GraduateStudent()
g.score = 9999
除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。
@property用来在类中定义规则,并且外部简单调用,即外部实例话后,不用调用方法来设置属性,而是直接设置属性
class Student(object):
@property
def score(self):
return self._score
@score.setter # 没有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()
60
>>> s.score = 9999
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
class Dog(Mammal, Runnable):
pass
只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。
class Student(object):
def __init__(self):
self.name = ‘Michael‘
def __getattr__(self, attr):
if attr==‘score‘:
return 99
else:
raise AttributeError(‘\‘Student\‘ object has no attribute \‘%s\‘‘ % attr)
class Student(object):
def init(self, name):
self.name = name
def __call__(self):
print(‘My name is %s.‘ % self.name)
调用方式如下:
s = Student(‘Michael‘)
s() # self参数不要传入
My name is Michael.
通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
callable(Student())
Truecallable(max)
Truecallable([1, 2, 3])
Falsecallable(None)
Falsecallable(‘str‘)
False
from enum import Enum
Month = Enum(‘Monster‘, (‘Jan‘, ‘Feb‘, ‘Mar‘, ‘Apr‘, ‘May‘, ‘Jun‘, ‘Jul‘, ‘Aug‘, ‘Sep‘, ‘Oct‘, ‘Nov‘, ‘Dec‘))
#类似于字典的键值对的形式
print(Month.Jan)#返回Monster.Jan
for name, member in Month.__members__.items():
print(name, ‘=>‘, member, ‘,‘, member.value)
#结果如下
‘‘‘Jan => Monster.Jan , 1
Feb => Monster.Feb , 2
Mar => Monster.Mar , 3
Apr => Monster.Apr , 4
May => Monster.May , 5
Jun => Monster.Jun , 6
Jul => Monster.Jul , 7
Aug => Monster.Aug , 8
Sep => Monster.Sep , 9
Oct => Monster.Oct , 10
Nov => Monster.Nov , 11‘‘‘
另一种方法,可见,既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。
from enum import Enum, unique
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
@unique装饰器可以帮助我们检查保证没有重复值。
访问这些枚举类型可以有若干种方法:
day1 = Weekday.Mon
print(day1)
Weekday.Monprint(Weekday.Tue)
Weekday.Tueprint(Weekday[‘Tue‘])
Weekday.Tueprint(Weekday.Tue.value)
2print(day1 == Weekday.Mon)
Trueprint(day1 == Weekday.Tue)
Falseprint(Weekday(1))
Weekday.Monprint(day1 == Weekday(1))
TrueWeekday(7)
Traceback (most recent call last):
...
ValueError: 7 is not a valid Weekdayfor name, member in Weekday.members.items():
... print(name, ‘=>‘, member)
...
Sun => Weekday.Sun
Mon => Weekday.Mon
Tue => Weekday.Tue
Wed => Weekday.Wed
Thu => Weekday.Thu
Fri => Weekday.Fri
Sat => Weekday.Sat
原文:https://www.cnblogs.com/lyzz1314/p/12743498.html