Python学习之路 —— @property 原理剖析及实现

熟悉 Python 的朋友们都知道,Python 中有一个可以让方法像属性一样访问的 @property 装饰器,这个装饰器主要用来控制我们的属性。今天就带大家来解析这个装饰器。

分析功能

首先我们应该知道它实现了怎样的功能:

查看官方文档:

"""
    Property attribute.
    
      fget
        function to be used for getting an attribute value
      fset
        function to be used for setting an attribute value
      fdel
        function to be used for del'ing an attribute
      doc
        docstring
    
    Typical use is to define a managed attribute x:
    
    class C(object):
        def getx(self): return self._x
        def setx(self, value): self._x = value
        def delx(self): del self._x
        x = property(getx, setx, delx, "I'm the 'x' property.")
    
    Decorators make defining new properties or modifying existing ones easy:
    
    class C(object):
        @property
        def x(self):
            "I am the 'x' property."
            return self._x
        @x.setter
        def x(self, value):
            self._x = value
        @x.deleter
        def x(self):
            del self._x
    """

实现

首先要明确的是,property 是一个类装饰器!setter、getter、deleter都是这个类的方法!

实现代码:

class MyProperty(object):
    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.__fget = fget
        self.__fset = fset
        self.__fdel = fdel
        self.__doc__ = doc

    def __get__(self, instance, owner):
        return self.__fget(instance)

    def __set__(self, instance, value):
        # 判断是否设置了setter方法
        if self.__fset is None:
            raise AttributeError("this attribute is read-only")
        self.__fset(instance, value)

    def __delete__(self, instance):
        # 判断是否设置了deleter方法
        if self.__fdel is None:
            raise AttributeError("this attribute cannot delete")
        self.__fdel(instance)

    def getter(self, func):
		self.__fget = func
        return self

    def setter(self, func):
        self.__fset = func
        return self

    def deleter(self, func):
        self.__fdel = func
        return self

示例代码:

class Student(object):
    def __init__(self):
        self.__age = 18

    @MyProperty
    def age(self):
        return self.__age

    @age.setter
    def age(self, value):
        self.__age = value

    @age.deleter
    def age(self):
        del self.__age


john = Student()
print(john.age)
john.age = 15
print(john.age)
del john.age

__get、__set______、__delete__ 都是属性描述符的方法

初始化

当我们初始化类时,被装饰的方法(age)传递给 MyProperty 描述符,实例会保存传递来的方法,并返回一个 MyProperty 的实例,实例的名字和方法名一样。

age 方法
保存 age 方法
返回 age 实例
Student
MyProperty
创建 age 实例

当我们调用 john.age 时,实际上调用的是 MyProperty 的实例,然后实例再调用初始化类时保存的方法,再将被调用的方法的返回值返回给 john.age,这样就达到了像调用属性一样调用方法的效果。

调用 john.age
调用 保存的 age 方法
返回 age方法返回的值
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@propertyPython的一个内置修饰符,用于将一个方法变成属性调用。在面向对象编程,有时候我们希望通过调用对象的属性来获得或设置其值,而不是直接调用方法。这样可以使代码更加简洁和易读。 @property的使用方式是,在需要被修饰的方法上方加上@property装饰符。这样,当我们调用对象的该方法时,就会像访问属性一样来访问。 @property修饰的方法通常用于获取属性的值,因此被称为getter方法。此外,我们还可以使用@property来定义setter方法,用于设置属性的值。 @property与getter和setter方法的原理是通过实现特殊的方法来实现的。 对于getter方法,@property将其装饰的方法转换为只读的属性。当我们通过调用该属性时,实际上调用的是被装饰的方法。 对于setter方法,@方法名.setter装饰器用来定义一个名字与被装饰方法相同的方法,并通过该方法来修改属性的值。当我们给该属性赋值时,实际上调用的是被装饰的setter方法。 通过getter和setter方法的配合,@property可以使我们在获取和设置属性值时更加灵活和方便。比如,我们可以在setter方法进行属性值的校验和处理,确保属性值符合预期。 总结起来,@property提供了一种优雅和方便的方式来定义类的属性访问方法,使得我们可以像访问属性一样来调用这些方法。它的实现原理是通过装饰器和特殊的方法来实现的。这种方式使得代码更加简洁、易读,并且拥有更高的灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值