Python 如何正确使用__setattr__,避免无限递归
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17020115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use __setattr__ correctly, avoiding infinite recursion
提问by Alex
I want to define a class containing readand writemethode, which can be called as follows:
我想定义一个包含read和writemethode的类,可以这样调用:
instance.read
instance.write
instance.device.read
instance.device.write
To not use interlaced classes, my idea was to overwrite the __getattr__and __setattr__methods and to check, if the given name is deviceto redirect the return to self. But I encountered a problem giving infinite recursions. The example code is as follows:
为了不使用交错类,我的想法是覆盖__getattr__和__setattr__方法并检查给定的名称是否device将返回重定向到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)
As in __init__the code tried to create a new attribute x, it calls __setattr__, which again calls __setattr__and so on. How do I need to change this code, that, in this case, a new attribute xof selfis created, holding the value 1?
就像在__init__代码中尝试创建一个新属性一样x,它调用__setattr__,然后再次调用__setattr__,依此类推。我需要如何更改此代码,在这种情况下,将创建一个新属性x,self并保存值1?
Or is there any better way to handle calls like instance.device.readto be 'mapped' to instance.read?
或者有没有更好的方法来处理像instance.device.read被“映射”到的调用instance.read?
As there are always questions about the why: I need to create abstractions of xmlrpccalls, for which very easy methods like myxmlrpc.instance,device.readand similar can be created. I need to 'mock' this up to mimic such multi-dot-method calls.
因为总是有关于为什么的问题:我需要创建xmlrpc调用的抽象,为此myxmlrpc.instance,device.read可以创建非常简单的方法 like和 similar。我需要“模拟”它以模仿这种多点方法调用。
采纳答案by Bakuriu
You must call the parent class __setattr__method:
您必须调用父类__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)
Regarding the best-practice, since you plan to use this via xml-rpcI think this is probably better done inside the _dispatchmethod.
关于最佳实践,因为您计划通过xml-rpc我使用它,我认为这在_dispatch方法中可能会更好。
A quick and dirty way is to simply do:
一种快速而肮脏的方法是简单地执行以下操作:
class My(object):
def __init__(self):
self.device = self
回答by Vindolin
Or you can modify self.__dict__from inside __setattr__():
或者您可以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
回答by Danny Hpy
You can also use object.
您也可以使用object。
class TestClass:
def __init__(self):
self.data = 'data'
def __setattr__(self, name, value):
print("Attempt to edit the attribute %s" %(name))
object.__setattr__(self, name, value)
回答by Aviad Rozenhek
or you can just use @property:
或者你可以只使用@property:
class MyTest(object):
def __init__(self, x):
self.x = x
@property
def device(self):
return self

