首页 文章

在python中定义私有模块函数

提问于
浏览
185

根据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错了,还是我误解了什么?有没有办法将 do 模块的功能定义为私有?

8 回答

  • 0

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

  • 1

    在Python中,"privacy"依赖于"consenting adults'"级别的协议 - 你不能强迫它(在现实生活中超过你的能力;-) . 单个前导下划线意味着你不是 supposed 来访问它"from the outside" - two 领先的下划线(没有尾随下划线)更有力地传递信息......但是,最后,它仍然取决于社会习俗和共识: Python 's introspection is forceful enough that you can' t handcuff 世界上所有其他程序员都尊重你的意愿 .

    ((顺便说一下,虽然它是一个密切关注的秘密,但对于C来说也是如此:对于大多数编译器来说,在 #include 之前的 #define private public 文件中只需要一个简单的 #define private public 行就可以让狡猾的程序员对你的"privacy"哈希进行哈希...! - ))

  • 70

    class privatesmodule privates 之间可能存在混淆 .

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

    一个私人课程以 two underscores 开头(又名dunder,即d-ouble not-score)
    这样的变量名称为"mangled",包括类名等 .
    它仍然可以通过错位名称在类逻辑之外访问 .
    虽然名称修改可以作为防止未经授权访问的温和防范设备,但其主要目的是防止与祖先类的类成员发生可能的名称冲突 . 请参阅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
    >>>
    
  • 245

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

    如果在模块中定义专用名称,则可以将这些名称 will 导入到使用语法'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
    ...
    
  • 28

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

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

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

    如果你真的需要这种程度的隐私,那就是这样的 .

  • -5

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

    The Python Tutorial»Classes»Private Variables

  • 3

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

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

相关问题