Python面向对象编程第18篇 属性装饰器

Posted 不剪发的Tony老师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python面向对象编程第18篇 属性装饰器相关的知识,希望对你有一定的参考价值。

本篇我们学习 Python 属性装饰器(@property)的原理。

属性装饰器

上一篇中,我们介绍了如何利用 property 类定义类的属性。property 类的调用语法如下:

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

以下代码定义了一个 Person 类包含两个属性 name 和 age:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

使用 property 类定义 age 属性的 getter 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    def get_age(self):
        return self._age

    age = property(fget=get_age)

property() 方法接受一个 getter 方法作为参数,返回一个 property 对象。

以下示例创建了一个 Person 类实例,通过实例获取 age 属性的值:

john = Person('John', 25)
print(john.age)

输出结果如下:

25

另外,我们也可以直接调用 Person 对象的 get_age() 方法:

print(john.get_age())

也就是说,我们既可以利用 age 属性获取年龄,也可以通过 get_age() 方法获取年龄。这两种方式是不必要的重复,为了减少重复,我们可以将 get_age() 方法重命名为 age():

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    def age(self):
        return self._age

    age = property(fget=age)

property() 方法接受一个可调用对象(age),同时返回一个可调用对象。因此它是一个装饰器。我们可以使用 @property 装饰器装饰 age() 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

通过使用 @property 装饰器,我们可以简化类的属性定义。

Setter 装饰器

以下代码为 Person 类增加了一个 setter 方法(set_age),用于为 _age 属性赋值:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

    def set_age(self, value):
        if value <= 0:
            raise ValueError('The age must be positive')
        self._age = value

为了将 set_age 赋予 age 属性对象的 fset 参数,可以调用 age 属性对象的 setter() 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

    def set_age(self, value):
        if value <= 0:
            raise ValueError('The age must be positive')
        self._age = value

    age = age.setter(set_age)

setter() 方法接受一个可调用对象参数,同时返回另一个可调用对象(属性对象)。所以,我们可以使用 @age.setter 属性装饰器装饰 set_age() 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def set_age(self, value):
        if value <= 0:
            raise ValueError('The age must be positive')
        self._age = value

现在我们可以将 set_age() 方法重命名为 age() 方法,并且在 __init__() 方法中使用 age 属性:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value <= 0:
            raise ValueError('The age must be positive')
        self._age = value

总结来说,我们可以使用装饰器创建属性:

class MyClass:
    def __init__(self, attr):
        self.prop = attr

    @property
    def prop(self):
        return self._attr

    @prop.setter
    def prop(self, value):
        self._attr = value

在以上方式中,__attr 是私有属性,prop 是属性名。

以下示例使用 @property 装饰器为 Person 类创建了两个属性 name 和 age:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value <= 0:
            raise ValueError('The age must be positive')
        self._age = value

    @property
    def name(self):
        return self._age

    @name.setter
    def name(self, value):
        if value.strip() == '':
            raise ValueError('The name cannot be empty')
        self._age = value

总结

  • 属性装饰器(@property)可以创建类的属性。

以上是关于Python面向对象编程第18篇 属性装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象编程第20篇 删除属性

Python面向对象编程第20篇 删除属性

Python面向对象编程进阶

Python面向对象编程进阶

Python面向对象编程进阶

Python入门-6面向对象编程:06私有属性和私有方法(实现封装)-@property装饰器-get和set方法-总结