在python中定义私有模块函数

Defining private module functions in python

根据http:/ / / / /文档www.faqs.org diveintopython FileInfo _ private.html:

Like most languages, Python has the
concept of private elements:

  • Private
    functions, which can't be called from
    outside their module

然而,如果一个文件的定义:

1
2
#a.py
__num=1

和:

1
2
3
#b.py
import a
print a.__num

当我运行它打印出b.py1没有给任何异常。diveintopython是错误的,或我misunderstand的东西吗?有一些单和待办事项模块的功能定义为一私人?


在python中,"隐私"取决于"同意的成年人"的协议水平——你不能强迫它(比你在现实生活中所能做的还要多;—)。一个前导下划线意味着您不应该"从外部"访问它——两个前导下划线(不带尾随下划线)可以更有力地传递消息…但是,归根结底,它仍然依赖于社会惯例和共识:Python的内省足够有力,以至于你不能用手铐束缚世界上的其他程序员来尊重你的愿望。

(BTW,虽然它是一个紧密持有的秘密,对于C++是一样的:对于大多数编译器来说,在EDCOX1之前的一个简单的EDCOX1 3行,4的EDCOX1×5的文件是所有狡猾的代码编写者的"隐私"的散列所需要的。-)


阶级私密和模块私密之间可能存在混淆。

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

一个班的私底下有两个下划线(也叫d under,即得分低的D-ouble)。这样一个变量的名称"mangled"包括类名等。它仍然可以通过损坏的名称在类逻辑之外访问。尽管名称管理可以作为一种轻微的防止未经授权访问的设备,但它的主要目的是防止可能的名称与祖先类的类成员冲突。见亚历克斯·马泰利有趣但准确地提到了同意的成年人,因为他描述了关于这些变量的惯例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> 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
>>>


这个问题没有得到完全的回答,因为模块隐私不是纯粹的传统,而且由于使用import,可能会或可能不会识别模块隐私,这取决于如何使用它。

如果在模块中定义私有名称,这些名称将被导入使用语法"import module_name"的任何脚本。因此,假设您在示例中正确地定义了模块private,_num,in a.py,like so.。

1
2
#a.py
_num=1

…您可以使用模块名称符号在b.py中访问它:

1
2
3
4
#b.py
import a
...
foo = a._num # 1

要仅从a.py导入非私有,必须使用From语法:

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

但是,为了清晰起见,从模块导入名称时最好是显式的,而不是用"*"导入所有名称:

1
2
3
4
#b.py
from a import name1
from a import name2
...


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

下面是私有类函数的示例:

1
2
3
4
5
6
7
class foo():
    def bar(self): pass
    def __bar(self): pass

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


可以添加内部函数:

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

如果你真的需要这样的隐私的话。


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

Python教程?课堂?私有变量


嵌入闭包或函数是一种方法。这在JS中很常见,但对于非浏览器平台或浏览器工作人员不需要。

在Python中,这看起来有点奇怪,但是如果确实需要隐藏一些东西,那么可能就是这样。更重要的是,使用PythonAPI并将需要隐藏在C语言(或其他语言)中的内容保留下来可能是最好的方法。如果失败,我将把代码放在函数中,调用它并让它返回您想要导出的项。


python有三种模式via.、private、public和protected,当导入模块时,只有public模式可以访问,所以private和protected模块不能从模块外部调用,即导入时。