如何正确使用__setattr__,避免无限递归

时间:2013-06-10 08:53:13

标签: python python-2.7 getattr setattr

我想定义一个包含readwrite方法的类,可以按如下方式调用:

instance.read
instance.write
instance.device.read
instance.device.write

为了不使用隔行扫描类,我的想法是覆盖__getattr____setattr__方法并检查,如果给定名称为device,则将返回值重定向到{{1} }。但是我遇到了一个无限递归的问题。示例代码如下:

self

class MyTest(object): def __init__(self, x): self.x = x def __setattr__(self, name, value): if name=="device": print "device test" else: setattr(self, name, value) test = MyTest(1) 代码尝试创建新属性__init__时,它会调用x,再次调用__setattr__,依此类推。如何更改此代码,在这种情况下,会创建__setattr__的{​​{1}}新属性,并保留值x

或者有没有更好的方法来处理self之类的呼叫被“映射”到1

因为总是存在关于原因的问题:我需要创建instance.device.read调用的抽象,为此可以创建非常简单的方法,如instance.read和类似的方法。我需要'模拟'这样来模仿这种多点方法调用。

5 个答案:

答案 0 :(得分:45)

您必须调用父类__setattr__方法:

class MyTest(object):

    def __init__(self, x):
        self.x = x

    def __setattr__(self, name, value):
        if name=="device":
            print "device test"
        else:
            super(MyTest, self).__setattr__(name, value)
            # in python3+ you can omit the arguments to super:
            #super().__setattr__(name, value)

关于最佳做法,因为您打算通过xml-rpc使用此功能,我认为在_dispatch方法中可能会做得更好。

快速而肮脏的方法就是:

class My(object):
    def __init__(self):
        self.device = self

答案 1 :(得分:18)

或者您可以在self.__dict__内修改__setattr__()

class SomeClass(object):

    def __setattr__(self, name, value):
        print(name, value)
        self.__dict__[name] = value

    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2


sc = SomeClass(attr1=1, attr2=2)

sc.attr1 = 3

答案 2 :(得分:3)

您也可以使用对象

tf.image.non_max_suppression 

答案 3 :(得分:1)

如果您不想指定可以设置或不能设置哪些属性,则可以拆分该类以将get / set挂钩延迟到初始化之后:

class MyTest(object):
    def __init__(self, x):
        self.x = x
        self.__class__ = _MyTestWithHooks

class _MyTestWithHooks(MyTest):
    def __setattr__(self, name, value):
        ...
    def __getattr__(self, name):
        ...

if __name__ == '__main__':
    a = MyTest(12)
    ...

如代码中所述,您将要实例化MyTest,因为实例化_MyTestWithHooks将导致与以前相同的无限递归问题。

答案 4 :(得分:0)

或者您可以只使用@property:

df1 = df[['ma', 'freq1']]
df2 = df[['phd', 'freq2']]
df1.merge(df2, left_on='ma', right_on='phd')

  ma  freq1 phd  freq2
0  a      1   a      8
1  b      2   b      9
相关问题