一、背景和场景
1.1 背景
python在进行oo编程的时候,可以设定一系列方法,为了满足oo的设计原则,python使用装饰器和property的方法来完成属性设定。
1.2 场景
在我输入一个数的时候,只需要通过对象访问就可以完成属性值的设定,举例:
1.2.1 传统
# 定义:
class Student(object):
def get_score(self):
return self._score
def set_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.set_score(60)
s.get_score()
1.2.2 使用property
# 定义:
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 # 直接完成赋值
二、使用
2.1 源码
通过查看property的源码可以看到property如下:
def __init__(self, fget=None, fset=None, fdel=None, doc=None): # known special case of property.__init__
def deleter(self, *args, **kwargs): # real signature unknown
""" Descriptor to change the deleter on a property. """
pass
def getter(self, *args, **kwargs): # real signature unknown
""" Descriptor to change the getter on a property. """
pass
def setter(self, *args, **kwargs): # real signature unknown
""" Descriptor to change the setter on a property. """
pass
通过查看可以知道property包含了四个值:获取函数(fget),设置值函数(fset),删除函数(fdel)以及doc属性。所以可以通过setter设置属性,deleter删除属性。
2.2 使用
在一个类中可以直接对一个函数使用property的方法进行装饰,在通过装饰函数.setter设置属性值即可,如果只是对函数使用property的方法,那么这个函数装饰的属性仅仅是可读,而不可修改。否在就会报不能够设置属性的错误。
class Screen(object):
_width = None
_height = None
# 读写
@property
def width(self):
return self._width # 注意这个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):
return self._width * self._height
s = Screen()
s.width = 1
s.height = 1
print(s.resolution)
三、总结
本次参考了廖雪峰关于property的讲解,看完之后查看了一下源码,知道了属性设置的函数以及一些过程。并且给出了一个test。
这种方法对于你要获取类的属性值有很好的帮助,不需要去构造一个set和get函数,直接使用装饰器就可以完成构造,但是会增加一些新的属性变量,比如width的属性值就需要一个新的变量去承接。总体来说这种方法对于类编程而言是一种不错的选择。