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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:14:54  来源:igfitidea点击:

How to use __setattr__ correctly, avoiding infinite recursion

pythonpython-2.7getattrsetattr

提问by Alex

I want to define a class containing readand writemethode, which can be called as follows:

我想定义一个包含readwritemethode的类,可以这样调用:

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__,依此类推。我需要如何更改此代码,在这种情况下,将创建一个新属性xself并保存值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