'exec' 不使用私有方法 Python

'exec' not working with private method Python

我知道你们中的大多数人都认为 exec 不应该被使用,但我有一些问题。

这是一个最小的例子,它可以工作:

class A:
    def __init__(self):
        exec('self.a = self.funct()')
    def funct(self):
        return 1
    def ret(self):
        return self.a
> obj = A()
> obj.ret()
1

但是,当我这样做时:

class A:
    def __init__(self):
        exec('self.a = self.__funct()')
    def __funct(self):
        return 1
    def ret(self):
        return self.a
> obj = A()
AttributeError: 'A' has no attribute '__funct'

有人知道为什么会有这种差异吗?

__name 名字是 class 私有的;这些名称在编译时以另一个下划线和 class 名称作为前缀。目的是防止名称与 subclasses 中使用的名称发生意外冲突。这些名称不是,对外部呼叫者是私有的。

引用 Reserved classes of identifiers section:

__*
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes.

Identifiers (Names) section:

Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used.

您的情况是 exec() 推迟编译,有效地编译该调用 隔离 。 class 上下文消失了,因此不会发生任何修改。

因此,您需要手动应用自动前缀:

exec('self.a = self._A__funct()')

如果您正在使用 Python 3,您可以使用 __class__ 闭包 normally available for the super() function 访问当前方法定义的 class 名称:

exec('self.a = self._{0.__name__}__funct()'.format(__class__))

现在,除非您真的计划让您的 class 广泛地被 class 编入 third-party 代码中,这样您就不必担心意外地与内部实现细节发生冲突,否则您根本不应该使用 double-underscore 名称。坚持使用 single-underscore 个名字。

Python 私有方法 "disguised" 与代码中指定的标识符不同,您可以像 _classname__privateAttribute.

一样访问它们

具体发帖:

class A:
    def __init__(self):
        exec('self.a = self._A__funct()')
    def __funct(self):
        print("Hello")
    def ret(self):
        return self.a

obj = A()

我把打印的答案放在那里以检测它是否有效,它确实有效!