当函数确定实例时,如何在Python中设置实例属性?

时间:2018-05-26 02:21:52

标签: python-3.x oop

我想迭代选择的类实例并将成员变量设置为等于值。我可以通过以下方式访问成员值:

for foo in range(1,4): #class members: pv1, pv2, pv3
    bar[foo] ='{0}'.format(locals()['pv' + str(foo)+'.data'])

然而,当我尝试设置/改变这样的值时:

for foo in range(1,4): #class members: 
    '{0}'.format(locals()['pv' + str(foo)+'.data']) = bar[foo]

我明显得到错误:

SyntaxError: can't assign to function call

我尝试过几种方法来完成它但没有成功。我在实际代码中使用了比3更多的实例(大约250个),但我的问题很清楚。我查看了几个堆栈溢出问题,例如Automatically setting class member variables in Python - 和 - dynamically set an instance property / memoized attribute in python?但似乎没有人回答这个问题。在C ++中,我只使用指针作为中介。 Pythonic的做法是什么?

2 个答案:

答案 0 :(得分:0)

attr是一个有效的分配目标,即使它是表达式结果的attr。

for foo in range(1,3):
    locals()['pv' + str(foo)].data = bar[foo]
  

另一位开发人员写了几行关于setattr()的内容,主要是关于如何避免它。

     
    除非属性名称是动态的,否则

setattr是不必要的。

  
     

但他们并没有说出原因。你是否介意详细阐述为什么你把你的答案从setattr()转移出来?

在这种情况下,attr是data,它永远不会改变,所以在

for i in range(1, 3):
    setattr(locals()['pv' + str(i)], 'data', bar[i])

做同样的事情,这里不需要setattr.data =形式既足够好又通常是首选 - 它更快,意图更清晰 - 这就是我改变它的原因。另一方面,如果你需要在每个循环中更改attr名称,那么你需要它,例如。

for i in range(1,3):
    setattr(locals()['pv' + str(i)], 'data' + str(i), bar[i])

上面的代码设置名为data1data2data3的attrs,展开,相当于

pv1.data1 = bar[1]
pv2.data2 = bar[2]
pv3.data3 = bar[3]

我原本认为你的问题需要做这样的事情,这就是我首先使用setattr的原因。一旦我对它进行了测试并使其正常工作,我就发布它而没有注意到setattr不再需要。

如果attr名称在运行时发生了变化(其他开发人员的意思是" dynamic")那么你就不能使用点语法,因为你有一个字符串对象而不是静态标识符。使用setattr的另一个原因可能是在表达式中需要副作用。与C不同,赋值是Python中的语句。但像setattr这样的函数调用是表达式。

答案 1 :(得分:0)

以下是创建一个类的示例,该类明确允许通过索引或属性调用进行访问以更改内部变量。这通常不会被推广为良好的编程和#39;虽然。它没有明确定义人们应该与底层变量进行交互的规则。

__getattr__()函数的定义允许分配(object).a

__getitem__()函数的定义允许赋值 (object)['b']

class Foo(object):
    def __init__(self, a=None,b=None,c=None):
        self.a=a
        self.b=b
        self.c=c
    def __getattr__(self, x):
        return self.__dict__.get(x, None)
    def __getitem__(self, x):
        return self.__dict__[x]

print
f1 = Foo(3,2,4)
print 'f1=', f1.a, f1['b'], f1['c']

f2 = Foo(4,6,2)
print 'f2=', f2.a, f2['b'], f2['c']

f3 = Foo(3,5,7)
print 'f3=', f3.a, f3['b'], f3['c']

for x in range(1, 4):
    print 'now setting f'+str(x)
    locals()['f'+str(x)].a=1
    locals()['f'+str(x)].b=1
    locals()['f'+str(x)].c=1

print    
print 'f1=', f1.a, f1['b'], f1['c']
print 'f2=', f2.a, f2['b'], f2['c']
print 'f3=', f3.a, f3['b'], f3['c']

结果是

f1= 3 2 4
f2= 4 6 2
f3= 3 5 7
now setting f1
now setting f2
now setting f3

f1= 1 1 1
f2= 1 1 1
f3= 1 1 1