一、动态增加类的属性与方法
#类在定义时为空,后面做动态增加
class Student(object):
pass
s=Student()
#1 动态增加实例的属性
s.name = 'tian'
print(s.name)
#2 动态增加实例的方法,但是其他实例不能用
def set_agenow(self,age):
self.age=age
from types import MethodType
s.set_age=MethodType(set_agenow,s)
s.set_age(25)
print(s.age)
print(dir(s))
print(dir(Student))
#…… 'age', 'name', 'set_age'],说明确实加上去了
#3 动态增加类的方法,增加的方法中又增加了属性,
#这个会有些复杂……
# 结果:增加的方法所有实例都可以用
#但注意:增加的方法中增加的属性,是实例的属性,不是类的
def set_score_now(self,score):
self.score=score
Student.set_score=set_score_now
s1=Student()
s2=Student()
s1.set_score(80)#可以执行
s2.set_score(90)#可以执行
#但Student.set_score(90)会报错,虽然dir(Student)已经有个set_score方法,但是该方法是给实例调用的,参数有self和value两个,Student.set_score(90)参数不对
print(s1.score)#80
print(s2.score)#90
#print(Student.score)
#这一句会报错AttributeError: type object 'Student' has no attribute 'score',因#类根本没有这个属性
print(dir(s1))
print(dir(s2))
#'score', 'set_score'都有
print(dir(Student))#没有'score'属性,只有'set_score'方法,而且还不能对类用
#4 __slots__限制动态增加的属性
#注意 __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
s=Student()
#s.score = 99会报错,因为限制了智能有'name', 'age'
#AttributeError: 'Student' object has no attribute 'score'
class GraduateStudent(Student):
pass
g = GraduateStudent()
g.score = 9999
#子类不受slot限制
#除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__
二、类的装饰器@property
#Python内置的@property装饰器,把一个方法,变成可以像属性那样,做取值用
#@score.setter,把一个方法,变成可以像属性那样,作赋值用
#@property和score()同时,表示可读可写;只有@property,表示只读
#下面的score()本身是一个方法,本来的用法是s.score()
# 经过@property,可以像属性那样用s.score,不加括号
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
s = Student()
s.score = 60 # OK,实际转化为s.set_score(60)
s.score # OK,实际转化为s.get_score()
#练习:请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution
class Screen(object):
@property
def width(self):
return self._width
@width.setter
def width(self,value):
self._width=value
@property
def height(self):
return self._height
@height.setter
def height(self,value):
self._height=value
@property
def resolution(self):
self._resolution=self._width*self._height
return self._resolution
s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:
print('测试通过!')
else:
print('测试失败!')