Python对不可变成员变量的引用
我遇到了一个无法间接引用成员变量的问题 我有一个函数类,它只做一件事。此函数在执行过程中使用一个成员变量,使用哪个成员变量取决于输入参数cmd。下面是一些代码:Python对不可变成员变量的引用,python,Python,我遇到了一个无法间接引用成员变量的问题 我有一个函数类,它只做一件事。此函数在执行过程中使用一个成员变量,使用哪个成员变量取决于输入参数cmd。下面是一些代码: class Foo(object): def __init__(self): self.a = 0 self.b = 0 def bar(self, cmd): if cmd == "do_this": index = self.a
class Foo(object):
def __init__(self):
self.a = 0
self.b = 0
def bar(self, cmd):
if cmd == "do_this":
index = self.a
elif cmd == "do_that":
index = self.b
filename = "file-%d.txt" % index
fp = open("filename", "w")
# do some more things which depend on and *should* change
# the value of self.a or self.b
return
现在我明白了为什么这段代码不能满足我的要求。因为我们使用的是不可变的int类型,所以我们的变量index指的是成员变量self.a或self.b,而不是self.a或self.b本身的值。函数结束时,索引表示不同的值整数,但self.a和self.b不变
很明显,我的想法太像C++了。我想要一些相当于
index = &(self.a)
filename = "file-%d.txt" % *index
如何以Pythonic的方式实现这一点?在这种特殊情况下,我只需跟踪您感兴趣的属性的字符串名称。比如:
class Foo(object):
def __init__(self):
self.a = 0
self.b = 0
def bar(self, cmd):
if cmd == "do_this":
index_name = 'a'
elif cmd == "do_that":
index_name = 'b'
index = getattr(self, index_name)
filename = "file-%d.txt" % index
fp = open("filename", "w")
# do some more things which depend on and *should* change
# the value of index
# ^^^^^
setattr(self, index_name, index)
return
如果不想跟踪字符串,可以使用属性代理类将其抽象出来,如下所示:
class AttributeProxy(object):
def __init__(self, obj_inst, attr_name):
self.obj_inst, self.attr_name = obj_inst, attr_name
@property
def value(self):
return getattr(self.obj_inst, self.attr_name)
@value.setter
def value(self, value):
setattr(self.obj_inst, self.attr_name, value)
用法:
class Test(object):
x = 0
y = 1
test = Test()
x = AttributeProxy(test, "x")
y = AttributeProxy(test, "y")
print x.value # 0
x.value += 1
print x.value == y.value
当然,它仍然在幕后使用
getattr()
和setattr()
,但是客户端代码看起来更好一些。将x.value+=1
与setattr(obj,“x”,getattr(obj,“x”)+1)
frex进行比较。有很多方法可以做到这一点--setattr
将属性名称作为字符串,编写函数或方法,为每个属性进行设置,等等。其中一种方法非常清楚,可能很方便
class Foo(object):
def __init__(self):
self.values = {'a': 0, 'b': 0}
def bar(self, cmd):
if cmd == "do_this":
index = 'a'
elif cmd == "do_that":
index = 'b'
filename = "file-%d.txt" % index
f = open("filename", "w")
...
self.values[index] = something
避免使用属性名作为字符串的直觉通常是正确的(尽管在这种特殊情况下,这是一个很好的解决方案),避免通过字符串查找属性和变量的基本解决方案是“使用dict”。显然,如果由于值不可变而出现问题,请使其可变!这当然是一个完整的破解,可能不符合任何“Pythonic”的定义
我希望避免使用成员的字符串id。。。我只是觉得有点马虎。这是一种python风格的编码吗?对于间接操作对象属性的特定情况,使用
getattr()
和setattr()
几乎总是比其他方法更受欢迎,因为其他方法必然不那么明确。@Harry,大多数时候,避免使用getattr
和setattr
,这是谨慎的,但在这种情况下,这是相当有益的。它不会使适用的代码很难阅读或理解,也不会接受属性名称的任意值;查看我的答案。@TokenMacGuy、getattr
和setattr
比使用dict更受欢迎?请注意,这种ifif
/elif
链通常最好用dict替换({do_this':self.a,'do_that':self.b}
).你们的方法不起作用和价值的不变性无关。这让我觉得过于工程化了。这是更多需要理解、调试和测试的代码,没有真正的好处。完全可能。:-)如果属性不必绑定到对象实例,那就更好了。呵呵,我也想到了这个技巧,但是是的。。。不是最漂亮的代码!谢谢:)“将其放入列表”是如何添加间接级别的常用示例,但我不确定我是否见过这样的情况,我认为这似乎是最好的解决方案。
class Foo(object):
def __init__(self):
self.a = [0]
self.b = [0]
def bar(self, cmd):
if cmd == "do_this":
index = self.a
elif cmd == "do_that":
index = self.b
filename = "file-%d.txt" % index[0]
fp = open("filename", "w")
# do some more things which depend on and *should* change
# the value of self.a or self.b
index[0] = 42
return