静态变量中使用的理解看不到局部函数



(见下面EDIT的最后一个问题。原标题是为什么静态var中的静态var可以,而Python中的静态方法不可以?(

原始帖子:我有一个Python问题,与从静态变量引用静态方法非常相关,但并不完全相同。因此,在中引用静态方法的代码静态变量,例如

class A:
@staticmethod
def f(a):
return a*a
v = f(2)    # A.f(2) does not work either

是无效的(就我所知,在没有@staticmethod的情况下也保持不变(。好的然而,可以毫无问题地引用另一个静态变量:

class A:
i = 2
v = i * i    # not using A.i here
print(A.v)    # gives 4

在这里,对静态变量和静态方法进行不同处理的理由是什么?如果重要的话,我正在尝试Python 3.6。

编辑:

gilch建议将其视为一个名称空间确实有所帮助。然而,现在我意识到我的测试用例过于简单化了。由于某种原因,初始化列表/字典失败:

class A:
def f(a):  return a*a
i = f(2)                           #works, indeed
lst = [2, 3, 4]
lst2 = [ v*v for v in lst]         #works
lst3 = [ f(v) for v in lst]        #fails??
dct =  { f(v) : v for v in lst }   #fails??

当然,如果f在A之外定义,最后两行都有效。所以这可能是一个范围问题。。。

因为staticmethod不可调用。它们是通过点(.(访问时返回可调用的描述符。类不存在,直到类主体执行之后。同时,它是一个命名空间,类似于模块,但具有稍微不同的作用域规则。在主体执行之后,名称空间被转储到类对象的__dict__中并被丢弃。所以这是有效的。

class A:
def f(a): return a*a
v = f(2)
f = staticmethod(f)

>>> A.v
4
>>> A.f(2)
4

这也适用于

class A:
@staticmethod
def f(a): return a*a
v = f.__get__(...)(2)

省略号没有任何意义。@staticmethod__get__()没有使用它的参数。(它不可能是None,或者它需要另一个参数。但我们还没有一个类或实例来给出它。(


由于某种原因初始化列表/字典失败:

这是由于我前面提到的"略有不同的作用域规则"。

理解像生成器一样编译——包含yield的函数。因此,由于类似的原因,这将失败:

class A:
def f(a): return a*a
xs=[2,3,4]
def comp(it):
for i in it:
yield f(i)
ys=list(comp(xs))

请记住,我说过body命名空间已被丢弃。通常,方法是在类主体执行之后调用的。因此,编译方法是为了查找不是在全局命名空间中本地定义的名称,而不是可能已经不存在的临时类主体命名空间。如果需要,可以将这个临时名称空间保存在某个地方,例如

class A:
def f(a): return a*a
lst=[2,3,4]
global ns
ns = locals()
lst2=[ns['f'](v) for v in lst]

>>> A.lst2
[4, 9, 16]

您也可以用老式的方式进行理解,以避免编译生成器:

class A:
def f(a): return a*a
lst=[2,3,4]
lst2=[]
for v in lst: lst2.append(f(v))
dct={}
for v in lst: dct[f(v)] = v

或者,您可以等到有了要处理的类对象之后(此时临时命名空间已转储到对象的__dict__中,因此它们可用作attrs(:

class A:
@staticmethod
def f(a):  return a*a
lst = [2, 3, 4]
A.lst2 = [A.f(v) for v in A.lst]

最新更新