【问题标题】:Reference to (module only) global function within a class method在类方法中引用(仅限模块)全局函数
【发布时间】:2015-11-07 21:52:19
【问题描述】:

在python中,我们可以很容易地通过它的名字来引用一个全局方法。

def globalfoo(a):
    print(a)


class myClass:
    def test(self):
        v = globalfoo
        v("hey")

t = myClass()
t.test()

现在在 python 中,也可以通过在其前面加上两个下划线来“隐藏”一个(类)方法。 - 我认为(!)一个人可以对全局函数做同样的事情——只制作一个全局函数模块。 (与 C++ 类似,可以决定将函数声明不在头文件中,因此它仅对当前编译单元可见)。

然后我尝试将其结合起来:

def __globalfoo(a):
    print(a)


class myClass:
    def test(self):
        v = __globalfoo
        v("hey")

t = myClass()
t.test()

但是这似乎不起作用,会引发一个错误,即“_myCLass__globalfoo”未定义。那么我如何让这两件事都起作用:引用一个函数。并从外部范围隐藏功能?
在这种情况下,静态方法是唯一/最佳解决方案吗?

【问题讨论】:

  • 为什么不在类中定义该函数?
  • 是的,@staticmethod 是一个不错且干净的解决方案。
  • @DanielSanchez 因为该函数需要类中的任何内容。它也不是特别与类耦合。对于其他类,它也可能是一个有用的实用函数。但它过于具体,无法公开:它基本上是一个经过精心设计的数学方程,部分求解。
  • @paul23 但是如果这个函数会被多个类使用,你为什么要私有化呢?
  • 您无法对其他模块隐藏该功能,所以我认为您的问题没有实际意义。

标签: python function-pointers encapsulation


【解决方案1】:

我认为(!)一个人可以对全局函数做同样的事情——只创建一个全局函数模块。

你错了。为模块级函数使用双下划线名称不会阻止它在其他模块中使用。有人仍然可以做import yourmodule,然后调用yourmodule.__globalfoo

双下划线名称修改行为在the docs中定义:

__spam 形式的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为 _classname__spam,其中类名是当前类名,前导下划线被去除。只要它出现在类的定义中,这种修饰就不会考虑标识符的语法位置。

它纯粹是文本替换,不考虑双下划线名称所指的内容(如果有的话)。它只取出现在类定义中任何地方的任何标识符,看起来像__blah,并将其更改为_class__blah。它特定于类定义,不会出现在模块级函数中。

最好的做法是在您的函数前加上一个下划线,并说明它不是公共 API 的一部分,模块的用户不应依赖它。试图“强制执行”这种隐私不会有任何好处。

【讨论】:

  • 嗯让我想知道我现在是否应该使用静态方法。 (背景我正在编写轨道力学模拟。其中一部分是求解开普勒方程:M = E + ecc * sin(E) for "E"。这不能用代数方式完成。最好的数值方法需要第一个 &二阶导数(作为函数指针)。所以我提供了这个集合。
  • @paul23:我在回答中添加了一些内容。你应该做的是用一个下划线命名它,并记录它不是公共 API 的一部分,人们不应该使用它。试图强制执行这种保护是徒劳的。
【解决方案2】:

在python中,一般来说,我们不会那么努力地让其他东西无法访问。我们相信其他开发人员不会修改和访问他们不应该修改的东西。无论如何,语言的工作方式几乎不可能使这些东西完全无法访问。

你能做的有两件事。模块中内部函数的标准符号是一个下划线——其他程序员应该知道不要干预这些函数。 Python 甚至在某些方面支持该约定 - 当像这样导入时:

from module import *

这不会导入带下划线前缀的名称。

另一种方法是在模块末尾发送del method。不是很传统,但如果你必须它实现你想做的事情:

def func():
    pass
...
...
del func

【讨论】:

    猜你喜欢
    • 2019-05-23
    • 1970-01-01
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    相关资源
    最近更新 更多