在python中定义私有模块函数

时间:2009-10-10 05:30:21

标签: python function module private

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

  

与大多数语言一样,Python也有   私人要素的概念:

     
      
  • 私人   函数,无法调用   在他们的模块之外
  •   

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

#a.py
__num=1

#b.py
import a
print a.__num

当我运行b.py时,它打印出1而不给出任何异常。 diveintopython错了,还是我误解了什么?有没有办法将模块的功能定义为私有?

9 个答案:

答案 0 :(得分:269)

在Python中,“隐私”取决于“同意成年人”的协议级别 - 你不能强制它(在现实生活中不能超过;-)。单个前导下划线表示您不是假设“从外部”访问它 - 两个前导下划线(没有尾随下划线)更有力地传递消息......但是,最后,它仍然取决于社会习俗和共识:Python的内省足够强大,你不能手铐世界上其他所有程序员都尊重你的意愿。

((顺便说一句,虽然这是一个密切关注的秘密,但C ++也是如此:对于大多数编译器,#define private public #include文件之前的简单.h行就是它的全部内容需要狡猾的程序员来制作你的“隐私”...! - ))

答案 1 :(得分:252)

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

模块私有一个下划线为开头 使用导入命令的from <module_name> import *形式时,不会复制此类元素;但是,如果使用import <moudule_name>语法(see Ben Wilhelm's answer),则会导入它 只需从问题示例的a .__ num中删除一个下划线,它就不会显示在使用from a import *语法导入a.py的模块中。

class private 两个下划线开头(又名dunder,即d-double不足) 这样的变量的名称“被修改”以包括类名等 它仍然可以通过错位名称在类逻辑之外访问 虽然名称修改可以作为防止未经授权访问的温和防范设备,但其主要目的是防止可能与祖先类的类成员发生名称冲突。 请参阅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
>>>

答案 2 :(得分:73)

这个问题没有得到完全回答,因为模块隐私不仅仅是传统的,因为使用 import 可能会或可能不会识别模块隐私,具体取决于它的使用方式。

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

#a.py
_num=1

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

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

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

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

但是,为了清楚起见,最好在从模块导入名称时明确,而不是使用'*'导入所有名称:

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

答案 3 :(得分:29)

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

答案 4 :(得分:6)

您可以添加内部函数:

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

如果您确实需要这种隐私级别,那就是这样。

答案 5 :(得分:1)

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

The Python Tutorial»Classes»Private Variables

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

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

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

答案 8 :(得分:-7)

Python有三种模式,包括。,private,public和protected。虽然导入模块只能访问公共模式。因此,无法从模块外部调用私有模块和受保护模块,即导入模块时。