Bootstrap

@property python知乎_【python】__slots__与@property

一、动态增加类的属性与方法

#类在定义时为空,后面做动态增加

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('测试失败!')

;