访问模块类中的私有模块成员

2024-10-04 11:34:17 发布

您现在位置:Python中文网/ 问答频道 /正文

<>我非常喜欢C++在类中具有私有、受保护和公共作用域的特性。我还喜欢对库用户隐藏实现细节,防止库API用户无意中弄乱微妙的内部结构(例如,通过使用private作用域、匿名名称空间)。你知道吗

我知道Python对这一点的支持是有限的,这是争论的根源:有些人认为隐私应该通过一个下划线_bla来传递,而另一些人则认为应该同时使用单下划线和双下划线,_bla表示受保护,而__bla表示敏感的实现细节(例如,请参见What is the benefit of private name mangling in Python?)。你知道吗

所以,我想实现的是,在一个模块中有几个双下划线私有成员,然后从模块范围中定义的其他函数和类访问这些方法。你知道吗

从公共模块成员函数访问私有模块成员可以很好地工作,但是从模块中的类内部看,这似乎不起作用(如果不诉诸名称消除或解决方法):

#! /usr/bin/env python

def func1():
    print "in func1()"

def _func2():
    print "in _func2()"

def __func3():
    # will be name-mangled due to leading double-underscore
    print "in __func3()"

def publicFunc():
    print "publicFunc() start"
    __func3()
    print "publicFunc() end"

class Foo:
    def __init__(self):
        print "Foo.__init__() start"
        func1()
        _func2()
        __func3()
        # :( Doesn't work, gives
        # NameError: global name '_Foo__func3' is not defined
        print "Foo.__init__() end"

publicFunc()
f = Foo()

运行上述命令将打印以下内容:

publicFunc() start
in __func3()
publicFunc() end
Foo.__init__() start
in func1()
in _func2()
<... stack trace>
NameError: global name '_Foo__func3' is not defined

这不是我所期望的-我假设函数和类在词法范围和损坏方面的行为大致相同。我希望它会大致符合C++中的私有概念,在这里我可以从主类中定义的类访问私有细节,例如

#include <cstdio>

class A
{
public:
    class B
    {
    public:
        static void fooB() {  A::foo(); }
    };
private:
    static void foo() { printf("in foo\n"); }
};

int main(int argc, char ** argv)
{
    A::B::fooB();
}

哪个指纹

in foo
<>我也希望它可以在C++中的匿名命名空间中起到类似的作用,这在编写库的用户不应该(或不一定)知道的实现细节时非常有用。你知道吗

以下是我尝试过的一些解决方法。我觉得没有一个特别优雅:

_funcList = [__func3]
__funcList = [__func3]

class Foo2:
    def __init__(self):
        print "Foo.__init__() start"
        func1()
        _func2()
        # __func3()

        # Work-around 1 - ugly but OK for globals, but not non-locals
        f3 = globals()["__func3"]
        f3()

        # Work-around 2 - misses the point, because now __func3 is
        # readily accessible without needing to mangle method names.
        # With my C++ hat on, this would be roughly equivalent to
        # returning a pointer to a private member function via
        # a protected member function.
        _funcList[0]()

        # Attempt 3 - hoping beyond hope that wrapping the method
        # tag in a private list doesn't work
        global __funcList
        __funcList[0]()
        # results in:
        # NameError: global name '_Foo2__funcList' is not defined
        print "Foo.__init__() end"

很遗憾,模块类的实现细节不能访问模块的私有成员(或者我在什么地方犯了错误?)。你知道吗

以下是我的问题:

  1. 在这种情况下,双下划线真的只用于防止子分类时的掩蔽问题吗?如果是这样的话,那么我认为应该在我想隐藏实现细节的所有其他情况下使用单下划线。你知道吗
  2. 有没有一种更优雅的方法来隐藏实现细节,它们的目标是同时具有“受保护”范围和“私有”范围的概念?你知道吗

谢谢!你知道吗


Tags: 模块nameinfooinitisdefprivate