在python中定义私有模块函数

2025-03-18 08:55:00
admin
原创
40
摘要:问题描述:根据http://www.faqs.org/docs/diveintopython/fileinfo_private.html:与大多数语言一样,Python 有私有元素的概念:私有函数,不能从模块外部调用但是,如果我定义两个文件:#a.py __num=1 和:#b.py import a pri...

问题描述:

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


解决方案 1:

在 Python 中,“隐私”取决于“成年人的同意程度”——你不能强迫它。单个前导下划线意味着你不应该“从外部”访问它——两个前导下划线(没有尾随下划线)传达的信息更有力……但最终,它仍然取决于社会习俗和共识:Python 的自省足够有力,你无法束缚世界上其他每个程序员来尊重你的意愿。

((顺便说一句,虽然这是一个严格保密的秘密,但对于 C++ 来说也是如此:对于大多数编译器来说,在编译你的文件#define private public之前只需一行简单的代码,狡猾的程序员就可以对你的“隐私”进行哈希处理...!-))#include`.h`

解决方案 2:

类私有属性模块私有属性之间可能会产生混淆。

私有模块以一个下划线开头,当使用import 命令的形式

时,这样的元素不会被复制;但是,如果使用语法,则会导入它(参见 Ben Wilhelm 的答案)from <module_name> import *`import <module_name>`

a.__num只需从问题示例中删除一个下划线,它就不会显示在使用from a import *语法导入 a.py 的模块中。

私有类以两个下划线开头 (又名 dunder,即双下划线)

这样的变量的名称被“破坏”,包含类名等。

它仍然可以通过混乱的名称在类逻辑之外进行访问。

尽管名称修改可以作为一种温和的预防未经授权访问的手段,但其主要目的是防止与祖先类的类成员发生名称冲突。请参阅 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
>>>

解决方案 3:

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

如果您在模块中定义私有名称,则这些名称被导入到使用语法“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
...

解决方案 4:

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

解决方案 5:

您可以添加内部函数:

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

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

解决方案 6:

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

Python 教程»类»私有变量

解决方案 7:

抱歉我回答晚了,但是在模块中,您可以像这样定义要“导出”的包:

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

我的模块/__init__.py

# only imports certain functions from library
from .library import hello

主程序

import mymodule
mymodule.hello()

尽管如此,仍然可以访问功能,

from mymodule.library import _hello
print(_hello('world'))

但这种方法让它不那么明显

解决方案 8:

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

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

解决方案 9:

参见PEP8 指南:

方法名称和实例变量

使用函数命名规则:小写并用下划线分隔单词,以提高可读性。

仅对非公共方法和实例变量使用一个前导下划线。

为了避免与子类发生名称冲突,请使用两个前导下划线来调用 Python 的名称修改规则。

Python 将这些名称与类名混杂在一起:如果类 Foo 有一个名为 __a 的属性,则它不能被 Foo.__a 访问。(坚持的用户仍然可以通过调用 Foo._Foo__a 获得访问权限。)通常,双前导下划线仅应用于避免与设计为子类的类中的属性发生名称冲突。

为继承而设计

始终确定类的方法和实例变量(统称为“属性”)应为公共还是非公共。如果有疑问,请选择非公共;稍后将其设为公共比将公共属性设为非公共更容易。

公共属性是您希望与类无关的客户端使用的属性,并且您承诺避免向后不兼容的更改。非公共属性是不打算由第三方使用的属性;您无法保证非公共属性不会更改甚至被删除。

我们在这里不使用术语“私有”,因为在 Python 中没有属性是真正私有的(通常不需要不必要的工作)。

解决方案 10:

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

打印三次.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

其他文件.py

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

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

解决方案 11:

Python 有三种模式,即私有、公共和受保护。导入模块时,只有公共模式可访问。因此,私有和受保护的模块不能从模块外部调用,即在导入时。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用