python内置装饰器---- @property

最近看Robotframe中SeleniumLibrary 源码,发现源代码中存在许多@property,因此看下python中内置的装饰器。
简言之,python 内置的装饰器常见为3个 ,分别为@property 、@classmethod和@staticmethod。

property 源码分析

查看property定义 class property(fget=None, fset=None, fdel=None, doc=None) ,说明property是一个类,包含3个可调用参数,和一个str的参数。返回为一个 property 属性。


class property(object):
   def __init__(self, fget: Optional[Callable[[Any], Any]] = ...,
                fset: Optional[Callable[[Any, Any], None]] = ...,
                fdel: Optional[Callable[[Any], None]] = ...,
                doc: Optional[str] = ...) -> None: ...
   def getter(self, fget: Callable[[Any], Any]) -> property: ...
   def setter(self, fset: Callable[[Any, Any], None]) -> property: ...
   def deleter(self, fdel: Callable[[Any], None]) -> property: ...
   def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ...
   def __set__(self, obj: Any, value: Any) -> None: ...
   def __delete__(self, obj: Any) -> None: ...
   def fget(self) -> Any: ...
   def fset(self, value: Any) -> None: ...
   def fdel(self) -> None: ...

采用测试代码 python 版本为3.5.2

class C:
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x

    def setx(self, value):
        self._x = value

    def delx(self):
        del self._x

test = C()
x = property(test.getx,test.setx,test.delx,"I'm the 'x' property.")
test.x = 5
print(test.x)
del test.x

通过x = property(test.getx,test.setx,test.delx,"I'm the 'x' property.") 将x变更为类对象test的属性,可以对其进行 赋值 删除等操作。

property 作为装饰器应用

先看下面代码

class number(object):
   def __init__(self):
       self._x = 1000
   
   # @property
   def get_x(self):
       return self._x

test = number()
print(test.get_x())

在方法未添加装饰器前,get_x是一个可以修改的类的方法。而添加 @property装饰器后,get_x 从类的方法变更为类属性,从而调用方式也发生变化。
在之前的源代码分析中,property可以传入三个参数,前面的装饰器只装饰了一个函数,可以采用以下方式进行装饰三个函数


class C:
   def __init__(self):
       self._x = None

   @property
   def x(self):
       """I'm the 'x' property."""
       return self._x

   @x.setter
   def x(self, value):
       self._x = value

   @x.deleter
   def x(self):
       del self._x
test = C()
test.x = 5
print(test.x)

可以看出这与源码中的结果是一样的,实际上 源码中的代码 属于 装饰器的另一种调用方法。

小结

property 本身上就是采用类方式实现的装饰器,若在类内部使用,则将类中定义的方法转换为类的属性,且将对类属性的赋值、删除操作变得和变量操作一样,
可以说实现了多态。建议采用@property 装饰器的调用方法。应用方式

  • 单一装饰 直接采用@property 此装饰器 相当于调用fget, 将类中的方法装换为类属性
  • 进一步装饰 @x.setter 、 @x.deleter 将类方法变更为属性,且对属性进行 赋值和删除操作。
原文地址:https://www.cnblogs.com/Finding-bugs/p/14176672.html