How does the @property decorator work in Python?

后端 未结 13 2069
闹比i
闹比i 2020-11-21 04:49

I would like to understand how the built-in function property works. What confuses me is that property can also be used as a decorator, but it only

13条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-21 05:39

    property is a class behind @property decorator.

    You can always check this:

    print(property) #
    

    I rewrote the example from help(property) to show that the @property syntax

    class C:
        def __init__(self):
            self._x=None
    
        @property 
        def x(self):
            return self._x
    
        @x.setter 
        def x(self, value):
            self._x = value
    
        @x.deleter
        def x(self):
            del self._x
    
    c = C()
    c.x="a"
    print(c.x)
    

    is functionally identical to property() syntax:

    class C:
        def __init__(self):
            self._x=None
    
        def g(self):
            return self._x
    
        def s(self, v):
            self._x = v
    
        def d(self):
            del self._x
    
        prop = property(g,s,d)
    
    c = C()
    c.x="a"
    print(c.x)
    

    There is no difference how we use the property as you can see.

    To answer the question @property decorator is implemented via property class.


    So, the question is to explain the property class a bit. This line:

    prop = property(g,s,d)
    

    Was the initialization. We can rewrite it like this:

    prop = property(fget=g,fset=s,fdel=d)
    

    The meaning of fget, fset and fdel:

     |    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
    

    The next image shows the triplets we have, from the class property:

    __get__, __set__, and __delete__ are there to be overridden. This is the implementation of the descriptor pattern in Python.

    In general, a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol.

    We can also use property setter, getter and deleter methods to bind the function to property. Check the next example. The method s2 of the class C will set the property doubled.

    class C:
        def __init__(self):
            self._x=None
    
        def g(self):
            return self._x
    
        def s(self, x):
            self._x = x
    
        def d(self):
            del self._x
    
        def s2(self,x):
            self._x=x+x
    
    
        x=property(g)
        x=x.setter(s)
        x=x.deleter(d)      
    
    
    c = C()
    c.x="a"
    print(c.x) # outputs "a"
    
    C.x=property(C.g, C.s2)
    C.x=C.x.deleter(C.d)
    c2 = C()
    c2.x="a"
    print(c2.x) # outputs "aa"
    

提交回复
热议问题