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

标签 python python-3.x list-comprehension static-methods static-variables

(参见下面编辑中的最后一个问题。原始标题是为什么 static var in static var is ok but static method not ok in Python?)

原帖:我有一个与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 将其视为 namespace 的建议确实有帮助。然而现在我意识到我的测试用例太简单了。失败的是由于某种原因初始化列表/字典:

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 s 不可调用。他们是descriptors通过点( . )访问时返回可调用对象。在类主体执行之后之前,类不存在。同时,它是一个命名空间,类似于模块,但作用域规则略有不同。主体执行后, namespace 被转储到类对象的 __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 ,或者它需要另一个参数。但是我们还没有提供它的类或实例。)


What failed was initializing a list/dictionary for some reason:

这是由于我之前提到的“范围规则略有不同”。

推导式的编译方式类似于生成器——包含 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))

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

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__ 中,因此它们可用作属性):

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

A.lst2 = [A.f(v) for v in A.lst]

关于python - 静态变量中使用的理解看不到局部函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60918643/

相关文章:

file - python 3 : reading UCS-2 (BE) file

Python 3 - 多个字典键的交集

python - 有效地检查字符串列表中的字符串中的单词

python - 列表中的元素组成

python - 填充轮廓 OpenCV 的外部

python - 元组键值

python-3.x - 使用 "pip3 install xgboost"安装时出错

python - 使用列表理解将列表元素附加到嵌套列表中

python - 我在哪里放置我的 python 测试的 Assets ?

javascript - 如何从使用 'Document' 和/或 'Window' 的 Python 执行 JS