Python property() 高级


Python proprety() 基础

一、问题

管理对象的属性。


二、解决方案

定义为property

实例:增加对属性的类型检查。

class Person:
    def __init__(self, first_name):
        self._first_name = first_name

    # Getter函数
    @property
    def first_name(self):
        return self._first_name

    # Setter函数
    @first_name.setter
    def first_name(self, value):
        if not isinstance(value, str):
            raise TypeError('不是字符串。')
        self._first_name = value

    # Deleter函数
    @first_name.deleter
    def first_name(self):
        raise AttributeError('不能删除。')

a = Person('ke')
print(a.first_name)

输出:

ke

上述三个相关联的方法,名字必须一样。

第一个方法是Getter函数,使first_name成为一个属性。

其他两个方法给first_name属性添加SetterDeleter函数。只有first_name属性被创建后,后面的装饰器@first_name.setter@first_name.deleter才能被定义。

访问property时会自动触发gettersetterdeleter方法。

a = Person('ke')
print(a.first_name)

a.first_name = 42

del a.first_name

输出:

ke

TypeError: 不是字符串。
    
AttributeError: 不能删除。

GetterSetter函数中,是对_first_name属性进行操作,这是实际数据保存的地方。



三、讨论

property()具有fgetfsetfdel属性。

print(Person.first_name.fget)
print(Person.first_name.fset)
print(Person.first_name.fdel)

输出:

<function Person.first_name at 0x0000024E96FA5318>
<function Person.first_name at 0x0000024E99717A68>
<function Person.first_name at 0x0000024E99717AF8>

通常不会直接调用fgetfset,会在访问property时自动触发。



使用property,将所有访问接口统一起来,对方法的访问也是通过属性访问。

import math
class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def area(self):
        return math.pi * self.radius ** 2

    @property
    def diameter(self):
        return self.radius * 2

    @property
    def perimeter(self):
        return 2 * math.pi * self.radius

c = Circle(4)
print(c.radius)
print(c.area)
print(c.perimeter)

输出:

4
50.26548245743669
25.132741228718345

这里对半径、直径、周长、面积的访问都是通过对属性的访问。



posted @ 2021-12-21 10:11  做梦当财神  阅读(123)  评论(0编辑  收藏  举报