【问题标题】:How does assertion affect variable assignment in Python?断言如何影响 Python 中的变量赋值?
【发布时间】:2018-01-30 20:09:41
【问题描述】:

我在 Python 2.7 中遇到了列表别名或变量赋值的问题。我将向您展示一个最小的示例。 有和没有断言有两种不同的结果,我不知道断言为什么/如何影响这一点。

当我在下面显示的object_list 上附加一些内容时,它以某种方式覆盖了一个属性:

class Object1(object):                                                                                 

    def __init__(self):                                                                                    
        self.object_list = []  

    def add_thing(self, thing):                                                                                          
        # this next line makes all the difference
         assert thing.name not in [thing.name for thing in self.object_list], 'agent id already exists, use another one'
        self.object_list.append(thing)

class Thing(object):

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name

这是一个最小的例子:

带有断言

mfd = Object1()
myAgent = Thing('blah')
myAgent_2 = Thing('blew')

mfd.add_thing(myAgent)
mfd.add_thing(myAgent_2)

print mfd.object_list

>> [blah, blah]

没有断言

mfd = Object1()
myAgent = Thing('blah')
myAgent_2 = Thing('blew')

mfd.add_thing(myAgent)
mfd.add_thing(myAgent_2)

print mfd.object_list

>> [blah, blew]

有人可以向我解释一下上述断言是如何影响这一点的吗?谢谢。

【问题讨论】:

  • 为什么在列表推导中为循环变量使用与参数相同的名称?即使这没有导致这个错误(它不会在 3.x 中),它似乎故意混淆。
  • [thing.name for thing in self.object_list] ... 现在有thing= self.object_list[-1] ... 而不是[other.name for other in self.object_list]
  • @JoranBeasley 更好的是,使用集合理解,它在 Python 2 中没有泄漏范围(尽管我仍然不会使用相同的名称),至少那时你没有这样做连续两个 O(n) 操作。
  • 故事的寓意:使用 Python 3 :)
  • 或者定义你的类,这样你就可以做到new_thing not in self

标签: python python-2.7 list assert assertions


【解决方案1】:

在 python 2 中,在列表推导范围内进行的隐式赋值会泄漏到调用方范围之外的推导范围内。

因此在您的示例中,通过执行断言,thing 的值会发生变化,thing 的最终值是来自object_list 的最终值。因此,如果没有assert,您添加的内容与执行断言后的内容不同。

【讨论】:

  • 哇,这似乎是一个严重的设计缺陷。这在 python 3 中消失了?
  • 是的,python 3 没有这个。 IIRC 它是来自 c 优化的神器
猜你喜欢
  • 2012-05-19
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 2015-08-04
  • 1970-01-01
相关资源
最近更新 更多