在python中定义私有模块函数

问题:在python中定义私有模块函数

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

像大多数语言一样,Python具有私有元素的概念:

  • 私有函数,不能从其模块外部调用

但是,如果我定义两个文件:

#a.py
__num=1

和:

#b.py
import a
print a.__num

当我运行b.py它打印出1没有给出任何exceptions。diveintopython是错误的,还是我误会了某些东西?而且是有一些方法可以定义模块的功能为私有?

According to http://www.faqs.org/docs/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

However, if I define two files:

#a.py
__num=1

and:

#b.py
import a
print a.__num

when i run b.py it prints out 1 without giving any exception. Is diveintopython wrong, or did I misunderstand something? And is there some way to do define a module’s function as private?


回答 0

在Python中,“隐私”取决于“同意成年人”的协议级别-您不能强制执行它(比现实生活中的要多;-)。单个前导下划线表示您不应该 “从外部”访问它- 两个前导下划线(不带尾随下划线)可以更加有力地传达信息……但最终,它仍然取决于社交网络会议达成共识:Python的自省是有力的,以至于你无法手铐在世界上其他程序员尊重您的意愿。

((顺便说一句,尽管这是一个秘密的秘密,但对于C ++却是如此:在大多数编译器中,狡猾的编码人员只需花#define private public一行简单#include.h代码就可以对您的“隐私”进行散列…!-) )

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.

((Btw, though it’s a closely held secret, much the same holds for C++: with most compilers, a simple #define private public line before #includeing your .h file is all it takes for wily coders to make hash of your “privacy”…!-))


回答 1

类私有模块私有之间可能会有混淆。

模块私人与启动一个下划线
这样的元件不使用时沿复制from <module_name> import *导入命令的形式; 但是,如果使用import <moudule_name>语法将其导入(请参阅Ben Wilhelm的答案),
只需从问题示例的a .__ num中删除一个下划线,并且不会在使用该from a import *语法导入a.py的模块中显示该下划线。

类私有与开始两个下划线 (又名dunder即d-ouble下分数)
这样的变量有其名“错位”,以包括类名等
它仍然可以访问的类逻辑的外面,通过重整名称。
尽管名称改编可以用作防止未经授权访问的温和预防工具,但其主要目的是防止与祖先类的类成员发生可能的名称冲突。参见亚历克斯·马特利(Alex Martelli)有趣而准确地提及成年人的同意书,因为他描述了有关这些变量的约定。

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

There may be confusion between class privates and module privates.

A module private starts with one underscore
Such a element is not copied along when using the from <module_name> import * form of the import command; it is however imported if using the import <moudule_name> syntax (see Ben Wilhelm’s answer)
Simply remove one underscore from the a.__num of the question’s example and it won’t show in modules that import a.py using the from a import * syntax.

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

回答 2

由于模块隐私不是纯粹的常规,并且由于使用import可能会或可能不会识别模块隐私,这取决于使用方式,因此未完全回答此问题。

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

#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
...

This question was not fully answered, since module privacy is not purely conventional, and since using import may or may not recognize module privacy, depending on how it is used.

If you define private names in a module, those names will be imported into any script that uses the syntax, ‘import module_name’. Thus, assuming you had correctly defined in your example the module private, _num, in a.py, like so..

#a.py
_num=1

..you would be able to access it in b.py with the module name symbol:

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

To import only non-privates from a.py, you must use the from syntax:

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

For the sake of clarity, however, it is better to be explicit when importing names from modules, rather than importing them all with a ‘*’:

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

回答 3

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 allows for private class members with the double underscore prefix. This technique doesn’t work at a module level so I am thinking this is a mistake in Dive Into Python.

Here is an example of private class functions:

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

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

回答 4

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

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

如果您确实需要该级别的隐私,则应采用类似的方法。

You can add an inner function:

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

Something like that if you really need that level of privacy.


回答 5

这是一个古老的问题,但是标准文档现在涵盖了模块私有(一个下划线)和类私有(两个下划线)混合变量。

Python教程 » » 私有变量

This is an ancient question, but both module private (one underscore) and class-private (two underscores) mangled variables are now covered in the standard documentation:

The Python Tutorial » Classes » Private Variables


回答 6

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

在Python中,这似乎有些奇怪,但是如果确实需要隐藏某些东西,那可能就是这样。更重要的是,使用python API并保留需要隐藏在C(或其他语言)中的内容可能是最好的方法。如果没有,我会将代码放入函数中,调用该函数并使它返回要导出的项目。

embedded with closures or functions is one way. This is common in JS although not required for non-browser platforms or browser workers.

In Python it seems a bit strange, but if something really needs to be hidden than that might be the way. More to the point using the python API and keeping things that require to be hidden in the C (or other language) is probably the best way. Failing that I would go for putting the code inside a function, calling that and having it return the items you want to export.


回答 7

Python具有三种模式,分别是private,public和protected。在导入模块时,只能访问public模式。因此,不能从模块外部(即在导入时)调用private和protected模块。

Python has three modes via., private, public and protected .While importing a module only public mode is accessible .So private and protected modules cannot be called from outside of the module i.e., when it is imported .