在循环中创建实例变量返回None对象

时间:2017-09-10 22:51:11

标签: python python-3.x class attributes

我尝试了一个小trafficlight实现,并获得了以下代码:

def __init__(...):
    ...
    self.redLight = Light(color = "red", master = self.frame)     
    self.redLight.place(x = 10, y = 10)
    self.yellowLight = Light(color = "yellow", master = self.frame)
    self.yellowLight.place(x = 10, y = 40)
    self.greenLight = Light(color = "green", master = self.frame)
    self.greenLight.place(x = 10, y = 70)
    ...

我感到无聊,并试图在循环中定义这个相当冗余的代码:

def __init__(...):
    ...
    self.redLight = None
    self.yellowLight = None
    self.greenLight = None

    for l in [[self.redLight, "red", 10],
              [self.yellowLight, "yellow", 40],
              [self.greenLight, "green", 70]]:
        l[0] = Light(color = l[1], master = self.frame)
        l[0].place(x = 10, y = l[2])
    ...

我的理解是,它与第一个代码示例完全相同,但事实证明,它不会编写实例变量。当我在调试器中查看代码时,l[0]对象是Light-object ...

不是python按引用调用,所以l[0]应该直接写实例变量吗?

1 个答案:

答案 0 :(得分:2)

setattrgetattr的用途是什么:

def __init__(self):
    for l in [['redLight', "red", 10],
              ['yellowLight', "yellow", 40],
              ['greenLight', "green", 70]]:
        setattr(self, l[0], Light(color=l[1], master=self.frame))
        getattr(self, l[0]).place(x=10, y=l[2])

因为正如评论中所述,分配给l[0]只会更改本地变量l的内容,不会设置您实例上的属性。< / p>

请注意,这归结为:

>>> a = 1
>>> b = a
>>> b = 2  # assigning a new value to "b" doesn't change "a"!
>>> a
1

或:

>>> a = 1
>>> b = [a]
>>> b[0] = 2  # won't change "a".
>>> a
1

因此,虽然您可以通过分配到self.redLight来更改属性,但并不意味着您可以通过为包含对self.redLight值的引用的列表指定不同的值来更改属性