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

问题描述 投票:1回答:1

我有一个与Refering to static methods from static variables密切相关的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外部定义,则最后两行都可以使用。因此,这可能是范围问题...

python python-3.x static-methods static-variables
1个回答
2
投票

因为staticmethod不可调用。当通过点(descriptors)访问时,它们是.返回可调用对象。类不存在直到类主体执行after为止。同时,它是一个名称空间,类似于模块,但作用域规则略有不同。主体执行后,名称空间将转储到对象objet的__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))

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

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]
© www.soinside.com 2019 - 2024. All rights reserved.