Python 为什么我不能在模块级别调用此函数?

Python 为什么我不能在模块级别调用此函数?,python,scope,Python,Scope,问题[python 3.8.6] def __foo(): pass class MyClass: @staticmethod def bar(): __foo() MyClass.bar() 结果: NameError: name '_MyClass__foo' is not defined 观察结果 如果我将\uuufoo()替换为foo(),它运行良好 我意识到python在MyClass中寻找\uuufoo()。在C++中,我可以使用:

问题[python 3.8.6]

def __foo():
    pass

class MyClass:
    @staticmethod
    def bar():
        __foo()

MyClass.bar()
结果:

NameError: name '_MyClass__foo' is not defined
观察结果

  • 如果我将
    \uuufoo()
    替换为
    foo()
    ,它运行良好

  • 我意识到python在
    MyClass
    中寻找
    \uuufoo()
    。在C++中,我可以使用<代码>::y-()(代码)来显式地调用模块级的函数。python中是否有一个等价物

问题

  • 你能解释一下我为什么会犯这个错误吗

  • 如何保持
    \uuufoo()
    并从类内部调用它

分辨率

我对python中的命名约定有一个误解

类中的私有方法和符号具有双下划线前缀,但模块级别的相同符号具有单下划线前缀。

因为任何带有两个下划线作为前缀(而不是后缀)的名称在类定义语句中都会损坏。从

只能从中访问的“私有”实例变量 对象内部不存在于Python中。然而,有一个惯例 然后是大多数Python代码:前缀为 下划线(例如,
\u垃圾邮件
)应作为 API(无论是函数、方法还是数据成员)。它应该 被视为实施细节,可随时更改,恕不另行通知 注意

因为类私有成员有一个有效的用例(即 避免名称与子类定义的名称发生名称冲突) 对这种机制的支持是有限的,称为名称混乱。任何 垃圾邮件格式的标识符(至少两个前导下划线,至少 大多数尾随下划线)在文本上替换为
\u classname\uu spam
,其中classname是当前类名,去掉前导下划线。这种弄脏是不加考虑的 标识符的语法位置,只要它出现 在类的定义中

(增加重点)

最明智的做法是不要用两个下划线来命名函数。或者,您可以执行以下操作:

def __foo():
    pass

def bar():
    __foo()


class MyClass:
    bar = staticmethod(bar)


MyClass.bar()
或者老实说,只需将
bar
作为模块级函数

但同样,使用两个下划线没有多大意义。如果您想表示该函数不是模块的公共api的一部分,则应使用一个下划线:

def _foo():
    pass

@juanpa.arrivillaga将函数的范围限制为模块。如果我添加它作为后缀,它也可以工作。我需要找到python中正确命名的规则。这并没有将函数的范围限制在模块中。。。你认为为什么会这样?按照惯例,API的非公共部分使用单下划线。Thx-单下划线也可以使用。你能给我指一些描述所有下划线约定的文档吗?谢谢,你不能。在使用带星号的导入时,可以防止某些名称被导入,不过,您通常应该避免带星号的导入。按照惯例,您应该只使用一个下划线(它将自动从带星号的导入中排除,并且大多数基于python的工具(例如tab completion)都理解这一点,并且不会显示它),我还尝试使用下划线来编制文档。阅读代码时,了解哪些符号仅用于模块内,哪些符号用于模块外的应用程序非常有用。非常好!谢谢-我不知道python使用_;来破坏方法名。我将使用单下划线。@kfmfe04是的,如果您不注意,这肯定会让人困惑是的-我被甩了,因为我在类中使用了双下划线作为私有静态方法。我认为这条规则也适用于模块级-我错了@kfmfe04理解起来非常重要,python没有私有方法。正如文件中引用的部分所述。但是,要表示“这是私有的”,请在方法名称中使用一个下划线