根据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

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

模块私有以一个下划线开始 当使用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
...

Python有三种模式via。当导入一个模块时,只有public模式是可访问的。因此private和protected模块不能从模块外部调用,即当它被导入时。


这是一个古老的问题,但是模块私有(一个下划线)和类私有(两个下划线)被破坏的变量现在都包含在标准文档中:

Python教程»类»私有变量


嵌入闭包或函数是一种方法。这在JS中很常见,但对于非浏览器平台或浏览器worker来说不是必需的。

在Python中,这似乎有点奇怪,但如果确实需要隐藏一些东西,那可能是一种方法。更重要的是,使用python API并将需要隐藏在C(或其他语言)中的内容可能是最好的方法。如果做不到这一点,我会把代码放在一个函数中,调用它,让它返回你想要导出的项。


你可以添加一个内部函数:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

如果你真的需要那种程度的隐私的话。


对于方法:(我不确定这是否是你想要的)

print_thrice.py

def private(method):
    def methodist(string):
        if __name__ == "__main__":
            method(string)
    return methodist
    
@private
def private_print3(string):
    print(string * 3)

private_print3("Hello ") # output: Hello Hello Hello

other_file.py

from print_thrice import private_print3
private_print3("Hello From Another File? ") # no output

这可能不是一个完美的解决方案,因为您仍然可以“看到”和/或“调用”该方法。不管怎样,它不会执行。


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

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'))

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


见PEP8指南:

方法名称和实例变量

Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability. Use one leading underscore only for non-public methods and instance variables. To avoid name clashes with subclasses, use two leading underscores to invoke Python’s name mangling rules. Python mangles these names with the class name: if class Foo has an attribute named __a, it cannot be accessed by Foo.__a. (An insistent user could still gain access by calling Foo._Foo__a.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.

为传承而设计

Always decide whether a class’s methods and instance variables (collectively: “attributes”) should be public or non-public. If in doubt, choose non-public; it’s easier to make it public later than to make a public attribute non-public. Public attributes are those that you expect unrelated clients of your class to use, with your commitment to avoid backwards incompatible changes. Non-public attributes are those that are not intended to be used by third parties; you make no guarantees that non-public attributes won’t change or even be removed. We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work).