How to add property to a class dynamically?

前端 未结 24 2119
梦毁少年i
梦毁少年i 2020-11-22 12:44

The goal is to create a mock class which behaves like a db resultset.

So for example, if a database query returns, using a dict expression, {\'ab\':100, \'cd\'

24条回答
  •  迷失自我
    2020-11-22 13:10

    How to add property to a python class dynamically?

    Say you have an object that you want to add a property to. Typically, I want to use properties when I need to begin managing access to an attribute in code that has downstream usage, so that I can maintain a consistent API. Now I will typically add them to the source code where the object is defined, but let's assume you don't have that access, or you need to truly dynamically choose your functions programmatically.

    Create a class

    Using an example based on the documentation for property, let's create a class of object with a "hidden" attribute and create an instance of it:

    class C(object):
        '''basic class'''
        _x = None
    
    o = C()
    

    In Python, we expect there to be one obvious way of doing things. However, in this case, I'm going to show two ways: with decorator notation, and without. First, without decorator notation. This may be more useful for the dynamic assignment of getters, setters, or deleters.

    Dynamic (a.k.a. Monkey Patching)

    Let's create some for our class:

    def getx(self):
        return self._x
    
    def setx(self, value):
        self._x = value
    
    def delx(self):
        del self._x
    

    And now we assign these to the property. Note that we could choose our functions programmatically here, answering the dynamic question:

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

    And usage:

    >>> o.x = 'foo'
    >>> o.x
    'foo'
    >>> del o.x
    >>> print(o.x)
    None
    >>> help(C.x)
    Help on property:
    
        I'm the 'x' property.
    

    Decorators

    We could do the same as we did above with decorator notation, but in this case, we must name the methods all the same name (and I'd recommend keeping it the same as the attribute), so programmatic assignment is not so trivial as it is using the above method:

    @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
    

    And assign the property object with its provisioned setters and deleters to the class:

    C.x = x
    

    And usage:

    >>> help(C.x)
    Help on property:
    
        I'm the 'x' property.
    
    >>> o.x
    >>> o.x = 'foo'
    >>> o.x
    'foo'
    >>> del o.x
    >>> print(o.x)
    None
    

提交回复
热议问题