为什么我不能在模块级调用这个函数?
Why can I not invoke this function at module-level?
问题 [python 3.8.6]
def __foo():
pass
class MyClass:
@staticmethod
def bar():
__foo()
MyClass.bar()
结果:
NameError: name '_MyClass__foo' is not defined
观察结果
如果我将 __foo()
替换为 foo()
,它运行良好。
我意识到 python 正在 MyClass
中寻找 __foo()
。在 C++ 中,我可以使用 ::__foo()
在模块级别显式调用该函数。 python中是否有等价物?
问题
你能解释一下为什么我会收到这个错误吗?
如何保留 __foo()
并从 Class 中调用它?
分辨率
我对 python 中的命名约定有误解。
Private 方法和符号在 类 中具有 双下划线前缀 ,但模块级别的相同符号具有 单下划线前缀.
因为 任何 带有两个下划线作为前缀(而不是后缀)的名称在 class 定义语句中被破坏了。来自 the docs
“Private” instance variables that cannot be accessed except from
inside an object don’t exist in Python. However, there is a convention
that is followed by most Python code: a name prefixed with an
underscore (e.g. _spam
) should be treated as a non-public part of the
API (whether it is a function, a method or a data member). It should
be considered an implementation detail and subject to change without
notice.
Since there is a valid use-case for class-private members (namely to
avoid name clashes of names with names defined by subclasses), there
is limited support for such a mechanism, called name mangling. Any
identifier of the form __spam
(at least two leading underscores, at
most one trailing underscore) is textually replaced with
_classname__spam
, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard
to the syntactic position of the identifier, as long as it occurs
within the definition of a class.
(强调)
最明智的事情是不要用两个下划线命名你的函数。或者,您可以这样做:
def __foo():
pass
def bar():
__foo()
class MyClass:
bar = staticmethod(bar)
MyClass.bar()
或者老实说,只保留 bar
作为模块级函数。
但同样,使用两个下划线也没有多大意义。如果你想表明函数不是模块 public api 的一部分,那么你应该使用 single 下划线:
def _foo():
pass
问题 [python 3.8.6]
def __foo():
pass
class MyClass:
@staticmethod
def bar():
__foo()
MyClass.bar()
结果:
NameError: name '_MyClass__foo' is not defined
观察结果
如果我将
__foo()
替换为foo()
,它运行良好。我意识到 python 正在
MyClass
中寻找__foo()
。在 C++ 中,我可以使用::__foo()
在模块级别显式调用该函数。 python中是否有等价物?
问题
你能解释一下为什么我会收到这个错误吗?
如何保留
__foo()
并从 Class 中调用它?
分辨率
我对 python 中的命名约定有误解。
Private 方法和符号在 类 中具有 双下划线前缀 ,但模块级别的相同符号具有 单下划线前缀.
因为 任何 带有两个下划线作为前缀(而不是后缀)的名称在 class 定义语句中被破坏了。来自 the docs
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g.
_spam
) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form
__spam
(at least two leading underscores, at most one trailing underscore) is textually replaced with_classname__spam
, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.
(强调)
最明智的事情是不要用两个下划线命名你的函数。或者,您可以这样做:
def __foo():
pass
def bar():
__foo()
class MyClass:
bar = staticmethod(bar)
MyClass.bar()
或者老实说,只保留 bar
作为模块级函数。
但同样,使用两个下划线也没有多大意义。如果你想表明函数不是模块 public api 的一部分,那么你应该使用 single 下划线:
def _foo():
pass