特征属性

有时候,我们需要对数据属性给出更精确的控制。按照其他语言的的实现方法,可以编写 “getter”、“setter” 或 “deleter” 一类的方法。如下示例:

class Student:
    def __init__(self, name):
        self.name = name
        self.__is_male = None  # 为了演示目的,特别通过私有的布尔类型变量存储性别

    def get_gender(self):
        return '男' if self.__is_male else '女'

    def set_gender(self, gender):
        match gender.lower():
    case '男' | '男性' | 'male' | 'm' | 'man':
        self.__is_male = True
    case '女' | '女性' | 'female' | 'f' | 'woman' | 'w':
        self.__is_male = False
    case _:
        self.__is_male = None

    def del_gender(self):
        del self.__is_male


xiaoming = Student('小明')
xiaoming.set_gender('男')
print(xiaoming.get_gender())
xiaoming.del_gender

Python 有一个内置的 property 函数,用于创建一个特征属性 property 对象。其签名为:

    class property(fget=None, fset=None, fdel=None, doc=None)

property 对象有三个方法:getter()setter()delete(),可以分别通过 fgetfsetfdel 参数指定。这里 fget 是获取属性值的函数,fset 是用于设置属性值的函数,fdel 是用于删除属性值的函数,doc 用于为属性对象创建文档字符串。

可以通过为所定义的类创建一个 property 类型的类变量来定义一个托管属性,见下页示例。

使用 property() 函数:

class Student:
    def __init__(self, name):
        self.name = name
        self.__is_male = None  # 为了演示目的,特别通过私有的布尔类型变量存储性别

    def get_gender(self):
        return '男' if self.__is_male else '女'

    def set_gender(self, gender):
        match gender.lower():
    case '男' | '男性' | 'male' | 'm' | 'man':
        self.__is_male = True
    case '女' | '女性' | 'female' | 'f' | 'woman' | 'w':
        self.__is_male = False
    case _:
        self.__is_male = None

    def del_gender(self):
        del self.__is_male

    # gender 是一个托管的属性
    gender = property(get_gender, set_gender, del_gender, "I'm the 'gender' property.")


xiaoming = Student('小明')
xiaoming.gender = '男'
print(xiaoming.gender)  # 男
del xiaoming.gender

这里 xiaoming.gender 将调用其“getter”,xiaoming.gender = value 将调用其“setter”,del xiaoming.gender 将调用 “deleter”。

以上代码可进一步用 Python 的装饰器来实现,见下页代码。

装饰器为一种语法糖,它是返回值为另一个函数的函数。通常使用 @wrapper 形式的语法来进行函数变换,从而修改其他函数功能,使代码更简洁。

下页 @property 装饰器会创建一个与 gender() 方法同名的特征属性 gender,将该方法指定给其 “getter”,将 gender 的文档字符串设置为 "I'm the 'gender' property.",然后将同名的 gender() 方法分别指定给 gender 特征属性的 “setter” 和 “deleter” 方法。

使用 @property 装饰器:

class Student:
    def __init__(self, name):
        self.name = name
        self.__is_male = None

    @property
    def gender(self):
        """I'm the 'gender' property."""
        return '男' if self.__is_male else '女'

    @gender.setter
    def gender(self, gender):
        match gender.lower():
    case '男' | '男性' | 'male' | 'm' | 'man':
        self.__is_male = True
    case '女' | '女性' | 'female' | 'f' | 'woman' | 'w':
        self.__is_male = False
    case _:
        self.__is_male = None

    @gender.deleter
    def gender(self):
        del self.__is_male

xiaoming = Student('小明')
xiaoming.gender = '男'
print(xiaoming.gender)  # 男
del xiaoming.gender
方法重写课后作业