Python 如何正确使用_usetattr _;,避免无限递归
我想定义一个包含Python 如何正确使用_usetattr _;,避免无限递归,python,python-2.7,getattr,setattr,Python,Python 2.7,Getattr,Setattr,我想定义一个包含read和write方法的类,可以如下调用: instance.read instance.write instance.device.read instance.device.write class MyTest(object): def __init__(self, x): self.x = x def __setattr__(self, name, value): if name=="device":
read
和write
方法的类,可以如下调用:
instance.read
instance.write
instance.device.read
instance.device.write
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)
为了不使用交错类,我的想法是覆盖\uuu getattr\uuuuuuuuuu
和\uuuuuuu setattr\uuuuuuuuu
方法,并检查给定名称是否为设备
,以将返回重定向到self
。但是我遇到了一个问题,给出了无限递归。示例代码如下所示:
instance.read
instance.write
instance.device.read
instance.device.write
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)
正如在\uuuuu init\uuuuuuuuu
中,代码试图创建一个新的属性x
,它调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu setattr
,再次调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我需要如何更改此代码,在这种情况下,将创建一个新的self
属性x
,并保存值1
或者有没有更好的方法来处理像instance.device.read
这样的调用以“映射”到instance.read
因为总是有关于为什么的问题:我需要创建xmlrpc
调用的抽象,可以为其创建非常简单的方法,如myxmlrpc.instance、device.read
和类似的方法。我需要对其进行“模拟”以模拟此类多点方法调用。您必须调用父类\uuuu setattr\uuu
方法:
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)
关于最佳实践,由于您计划通过xmlrpc
使用此方法,因此我认为在方法内部进行此操作可能更好
一个快速而肮脏的方法就是简单地做:
class My(object):
def __init__(self):
self.device = self
或者您可以从\uuuuuu setattr\uuuuuuuu()内部修改self.\uuuuu dict\uuuuuuuuuuuuuuuu
:
您也可以使用对象
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)
或者您可以只使用@property:
类MyTest(对象):
定义初始化(self,x):
self.x=x
@财产
def设备(自身):
回归自我
如果不想指定哪些属性可以设置,哪些属性不能设置,可以拆分类以将get/set挂钩延迟到初始化之后:
类MyTest(对象):
定义初始化(self,x):
self.x=x
self.\uuuuu类\uuuuu=\uMyTestWithHooks
类_MyTestWithHooks(MyTest):
定义设置属性(自身、名称、值):
...
def _ugetattr _;(self,name):
...
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
a=MyTest(12)
...
正如代码中所指出的,您将需要实例化MyTest,因为用hooks实例化_MyTestWithHooks将导致与以前相同的无限递归问题。我喜欢快速而肮脏的方式:只需一行代码即可获得所需的行为!谢谢这句话在《巴库留》中也提到过。你能解释一下这句话到底在做什么吗?super(MyTest,self)。\uuuuu setattr\uuuuuuu(name,value)@Shahryar我的答案的第一行解释了这一点。它正在调用父类\uuuuu setattr\uuuu
方法super(Class,instance)
创建一个对象,该对象能够在instance
上调用Class
的父类的方法。在这种情况下,您也可以执行object.\uuuuu setattr\uuuuu(实例、名称、值)
,但是super
能够正确处理多重继承,应该是首选。@Shahryar,因为这甚至不是有效的python语法self[name]=value
相当于self.\uuuuu setitem\uuuuuu(name,value)
,大多数情况下未实现。如果您尝试使用setattr
内置函数,那么会发生setattr(self,name-value)
将递归调用\uuuuuuuu setattr\uuuuuuu
并最终进入无限循环。为什么不调用setattr(self,“\uu dict\uuuuuuuuuuu”,value)
,重复最初的无限递归问题?因为这不是设置\uuuuu dict\uuuuu
属性,gut获取它,然后在返回的dict上设置一个项,例如,它调用类似以下内容:getattr(self,“\uu dict\uuuuuu”)。\uuuuu setitem\uuuuuu(名称,值)
使用@propertyth这一内置类可以更轻松地解决此用例。所有类都继承自该类(即使是\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。请注意,所有对象都有uuu setattr_uuu方法,甚至一个字符串:“a”。uuu setattr_uuu
,因为所有类都继承自内置类对象
偶数字符串