【问题标题】:python string is default globalpython字符串是默认全局的
【发布时间】:2010-10-01 14:57:21
【问题描述】:

我对 Python 中的全局变量有疑问。 代码如下。如果我在功能测试中不使用全局 M, 它会发出错误。 但是为什么它不显示字符串 s 的错误。我没有将其声明为全球性的。

global M
M = []
s = "abc"

def test():
    ### global M
    print M 
    M.append(s)

打印 M UnboundLocalError:赋值前引用了局部变量“M”

【问题讨论】:

  • 请包含您收到的错误消息的文本。
  • 感谢您帮助格式化代码。
  • 如果您发布更多关于您要解决的问题的信息,我们可能会找到一种很好的方法来分解它,这样您就不需要使用全局变量。相信我,你不想这样做。也许发布另一个问题“我如何重构这段代码以摆脱全局变量......”
  • 我想这只是函数的一部分,在某个地方你有类似 M=...

标签: python string scope global


【解决方案1】:

如果我不在函数中使用全局 M 测试,会报错。

你的这个说法根本不是真的!!!

>>> M = []
>>> s = "abc"
>>> 
>>> def test():
...     M.append(s)
... 
>>> M
[]
>>> test()
>>> M
['abc']

我认为您混淆了两个完全不同的概念:

  1. 绑定一个barename——通常通过赋值(即=),但也可能 通过其他一些声明(def,&c)

  2. 调用方法(例如append)“可能”会改变对象 (仅当该对象是可变的并且该方法当然是突变器时,但是 当对象为列表且方法为append) 时适用)

我不确定为什么人们会混淆这两个截然不同的概念,但他们肯定可以。也许这是事实,一些非普通的“种类”赋值实际上是在“幕后”调用一个(特殊)方法,例如,赋值给限定名(a.b=c 实际上是调用type(a).__setitem__(a, b),所以,调用一个方法,不重新绑定任何裸名)和增强赋值(a+=b 实际上是在做a = type(a).__iadd__(a, b),所以,调用方法重新绑定一个裸名)。 p>

当且仅当您执行“1”时才需要global(唉):重新绑定一个barename(包括通过增强赋值重新绑定它,但包括任何其他特殊情况)。避开global,除非它真的是必不可少的(很多人会说它从来没有真正必不可少......在某些情况下只是“显然有点方便”;-)。

【讨论】:

  • @chnet 请将错误信息复制到您的问题中,而不是仅仅谈论它。你在强迫人们读懂你的想法,这也行不通。
  • @chnet,在函数 test 中添加 print M 语句我在我的答案中给出的 sn-p 工作得很好,所以,再次,你的声明是错误的。您的代码必须与上述有显着差异,我们无法猜测可能存在哪些差异,因为您一直对我们隐藏代码并做出虚假陈述而不是向我们展示代码!-)
【解决方案2】:

我不太确定你会得到什么错误,但你似乎使用了全局错误。

声明全局变量时不需要(也不推荐)使用 global 关键字。而是在函数内部使用它来指定不应创建局部变量。考虑 2 个不同的功能:

M = []

def test1():
    M = [1]

def test2():
    global M
    M = [2]

test1 将创建一个新的局部变量,而 test2 将写入全局 M

【讨论】:

    【解决方案3】:

    正如@Alex Martelli 指出的那样,您的代码如图所示不会产生错误,但是暂时搁置它以建立在@cobbal 的答案(抱歉我还不能评论)您需要非常小心 说到这里的范围

    在@cobbal 的回答中:

    def test1():
        M = [1]
    

    创建一个新变量 M 局部于函数 test1。但是,如果他没有像问题中所做的那样使用M.append(1)而不是分配M = [1],而不是创建一个新的局部变量,Python将从函数的局部范围查找到更高的范围,在这个在全局范围内确实已经有一个变量 M 指向一个空列表。在这种情况下,Python 会找到这个变量并简单地附加到现有列表中,从而导致全局 M 现在指向 [1]

    在第二个例子中:

    def test2():
        global M
        M = [2]
    

    global 关键字的使用对于避免否则会发生的本地分配至关重要。通过调用 global 在函数的本地范围内使用 M 将指向函数外部已经存在的 [] 对象。

    您可以通过在函数的各种形式中插入id(M) 来证明这一点,以显示哪些实现导致函数内部的M 指向全局或本地对象。

    【讨论】:

      猜你喜欢
      • 2018-10-04
      • 1970-01-01
      • 2015-06-21
      • 2012-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多