根据http://www.faqs.org/docs/diveintopython/fileinfo_private.html:

像大多数语言一样,Python具有 私有元素的概念: 私人 函数,这些函数不能被调用 在模块外

然而,如果我定义两个文件:

#a.py
__num=1

and:

#b.py
import a
print a.__num

当我运行b.py时,它输出1而不给出任何异常。是diveintopython错了,还是我误解了什么?是否有方法将模块的函数定义为私有?


当前回答

Python允许带有双下划线前缀的私有类成员。这种技术在模块级别上不起作用,所以我认为这是Dive Into Python中的一个错误。

下面是一个私有类函数的例子:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

其他回答

Python允许带有双下划线前缀的私有类成员。这种技术在模块级别上不起作用,所以我认为这是Dive Into Python中的一个错误。

下面是一个私有类函数的例子:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

可能会混淆类私有和模块私有。

模块私有以一个下划线开始 当使用import命令的from <module_name> import *形式时,不会复制这样的元素;但是,如果使用import <moudule_name>语法,则会导入它(参见Ben Wilhelm的回答) 只要从问题示例的a.__num中删除一个下划线,它就不会在使用from a import *语法导入a.py的模块中显示出来。

A class private starts with two underscores (aka dunder i.e. d-ouble under-score) Such a variable has its name "mangled" to include the classname etc. It can still be accessed outside of the class logic, through the mangled name. Although the name mangling can serve as a mild prevention device against unauthorized access, its main purpose is to prevent possible name collisions with class members of the ancestor classes. See Alex Martelli's funny but accurate reference to consenting adults as he describes the convention used in regards to these variables.

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>

In Python, "privacy" depends on "consenting adults'" levels of agreement - you can't force it (any more than you can in real life;-). A single leading underscore means you're not supposed to access it "from the outside" -- two leading underscores (w/o trailing underscores) carry the message even more forcefully... but, in the end, it still depends on social convention and consensus: Python's introspection is forceful enough that you can't handcuff every other programmer in the world to respect your wishes.

((顺便说一下,虽然这是一个严格保密的秘密,但对于c++来说也是如此:在大多数编译器中,在#包括你的.h文件之前,一个简单的#define private public line就可以让狡猾的编码器对你的“隐私”进行散列…!-))

这个问题没有得到完全的回答,因为模块私密性并不完全是常规的,而且使用import可能会识别模块私密性,也可能不会,这取决于它的使用方式。

如果你在一个模块中定义了私有名称,这些名称将被导入到任何使用'import module_name'语法的脚本中。因此,假设您在示例中正确定义了模块private, _num,在a.py中,如下所示..

#a.py
_num=1

..你可以在b.py中使用模块名符号来访问它:

#b.py
import a
...
foo = a._num # 1

要从a.py中只导入非私有对象,你必须使用from语法:

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

然而,为了清晰起见,在从模块中导入名称时最好显式,而不是用'*'导入它们:

#b.py
from a import name1 
from a import name2
...

抱歉我回答晚了,但是在一个模块中,你可以像这样定义包来“导出”:

mymodule
  __init__.py
  library.py
main.py

我的模块/库.py

# 'private' function
def _hello(name):
    return f"Hello {name}!"

# 'public' function which is supposed to be used instead of _hello
def hello():
    name = input('name: ')
    print(_hello(name))

mymodule里/ __init__ . py

# only imports certain functions from library
from .library import hello

main.py

import mymodule
mymodule.hello()

尽管如此,函数仍然可以被访问,

from mymodule.library import _hello
print(_hello('world'))

但这种方法使其不那么明显