你能在运行时更改python描述符的__get__方法吗?

时间:2012-02-29 04:39:43

标签: python decorator descriptor

全部,    正如标题所要求的那样,是否可以在运行时更改描述符的__get__方法。我正处于这样一种情况,即我在运行时有一个正在装饰和未修饰的功能。我希望这个函数的结果可以作为属性使用,类似于@property的作用。我研究了它并发现它是一个描述符,但似乎描述符'__get__方法是只读的。

class Test( object ):
    def __init__( self ):
        self._x = 10

    def get_x( self ):
        return self._x

    @property
    def x( self ):
        return self.get_x()

上面的代码粗略地完成了我想要的内容

  1. 该值在构造函数
  2. 中设置
  3. 我可以将get_x方法装饰到我内心的内容
  4. instance.x返回正确的值
  5. 我的问题是我不必创建get_x方法,因为它基本上没必要。我只是无法装饰x的__get__方法,因为它是只读的。

    背景

    我正在编写一个基于回合制的策略游戏,我正在使用装饰器来实现持久的条件。当我使用测试用例时,我能够有效地实现这些装饰器,但问题是,为了获得计算值,你必须使用函数调用,而不是属性访问。这似乎是个坏主意,因为获取描述单元的值会不一致地使用函数或属性。如果可以的话,我想标准化属性。

1 个答案:

答案 0 :(得分:4)

您可以覆盖默认"只读"使用简单继承property __get__属性的特征:

class MyProperty( property ): pass

class Test( object ):
    def __init__( self ):
        self._x = 10

    def get_x( self ):
        return self._x

    @MyProperty
    def x( self ):
        return self.get_x()

test = Test()

现在的问题是,即使重新定义Text.x属性的__get__属性,在test.x请求python运行时也会调用MyProperty.__get__(Test.x, test, Test)

所以你只能在那里重写它

MyProperty.__get__ = lambda self,instance,owner: ""the x attribute"

这里很好的选择是委托调用某些可重定义的属性,如

MyProperty.__get__ = lambda self,instance,owner: self.get(instance,owner)

从现在开始,您的财产的获取属性将完全控制。 此外,为每个类似属性的对象生成单独的类型也有不好的选择。 所以在好的情况下你可以做类似的事情:

class MyProperty( property ):
    def __get__(self,instance,owner) :
        if not instance: return self
        else: return self.get(instance,owner)

class Test( object ):
    def __init__( self ):
        self._x = 10

    def get_x( self ):
        return self._x

    @MyProperty
    def x( self ): pass

    @MyProperty
    def y(self): pass

    x.get = lambda self,clazz: self.get_x()
    y.get = lambda self,clazz: "the y property of " + clazz.__name__ + " object"

>>> test = Test()
>>> test.x
10
>>> test.y
'the y property of Test object'