一、背景和场景

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的属性值就需要一个新的变量去承接。总体来说这种方法对于类编程而言是一种不错的选择。

posted on 2021-07-26 19:39  蔚蓝色の天空  阅读(303)  评论(0编辑  收藏  举报