'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()
我把打印的答案放在那里以检测它是否有效,它确实有效!
我知道你们中的大多数人都认为 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 namedHam
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()
我把打印的答案放在那里以检测它是否有效,它确实有效!