无法使用类级别变量

2024-06-17 14:17:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下代码,但不起作用:

class Node:
    n = 5
    options = [ i / (n-1) for i in range(n)]


print("Success")

我得到的错误是:

    Traceback (most recent call last):
  File "/Users/ikkamens/Library/Preferences/PyCharm2019.2/scratches/counters.py", line 1, in <module>
    class Node:
  File "/Users/ikkamens/Library/Preferences/PyCharm2019.2/scratches/counters.py", line 3, in Node
    options = [ i / (n-1) for i in range(n)]
  File "/Users/ikkamens/Library/Preferences/PyCharm2019.2/scratches/counters.py", line 3, in <listcomp>
    options = [ i / (n-1) for i in range(n)]
NameError: name 'n' is not defined

但是,以下更改的版本仍然有效:

class Node:
    n = 5
    options = [ i / 4 for i in range(n)]


print("Success")

为什么我可以在range表达式中使用类级别变量,而不能在(n-1)表达式中使用?这是一个解释器错误还是有一些规则来解释这种行为?我试过使用3.8和3.6口译员


Tags: inpynodeforlinelibraryrangeusers
2条回答

我不知道为什么它不能以这种方式工作,但可能是口译员认为 (n-1) 在列表中是属于列表中的局部变量或循环的一部分。尽管我不确定

你可以这样做

class Node:
    global n
    n = 5
    options = [ i / (n-1) for i in range(n)]


print("Success")

从OP下的讨论可以看出,这里有两件事

< P><强>第一< /强>,在Python中,没有默认对象或类作用域,如C++中的隐式^ {< CD1>}。因此,在函数内部,您的作用域就是该函数,并且您没有对类上对象上定义的变量的“自由”名称访问权。这就是我们必须传递self的原因——我们需要显式包含对象(和类)的环境。这意味着如果我们有

class A:
    n = 5

我们只能在类级别定义中访问n,或者通过显式保存环境:

class A:
    n = 5
    a = range(n) # legal, evaluated in the class definition, where 'A' is defined and 'n' is part of the statement.
    def f():
        x = self.n # legal. As long you do not override self.n same as next
        x = A.n # legal, this is the class variable scope
        x = n # Error - we do not have 'n' for free. Even worse, if 'n' is a global variable, we are using that.

第二个,在Python3中,与Python2不同的是,列表理解被限定了范围。不再泄漏变量,并且class语句的主体实际上不是一个作用域(而是一个名称空间的定义),因此也不是定义实现理解的匿名函数的作用域。所以

class A:
    n = 5
    x = [n/a for a in range(n)]

可能被视为

class A:
    n = 5
    def _anonymous_function(param):
        return [n/a for a in range(param)]
    x = _anonymous_function(n)

通过这种方式,也许可以更清楚地解释为什么n在一个地方合法,而在另一个地方不合法。在range(n)中,与答案中第二个代码段中的第一个示例类似,我们仍然在类名称空间定义语句中,并“参见”n。另一方面,在理解体中,我们处于一个作用域(匿名)环境中,没有看到n,因为它不在外部(全局)作用域中,因为A是一个命名空间定义。这就是它在这里中断的原因,与另一个示例相反。在Python2中,这是可行的

相关问题 更多 >