【问题标题】:Accesing private module variable from class从类访问私有模块变量
【发布时间】:2014-02-09 18:56:20
【问题描述】:

我正在尝试了解 python 范围规则。为此,我尝试从同一模块中的类访问“非常私有”的变量

bar = "bar"
_bar = "underscore"
__bar = "double underscore"

def foo():
    print bar
    print _bar
    print globals()["__bar"]
    print __bar

class Foo:
    def __init__(self):
        print bar
        print _bar
        print globals()["__bar"]
        print __bar #NameError: global name '_Foo__bar' is not defined

foo()
Foo()

NameError 失败。我在规范中找不到任何相关内容。那么,为什么它会失败以及这种行为在哪里描述?

【问题讨论】:

  • 你能发布完整的输出吗?还是完整的异常消息?
  • 是的,已删除,因为 - 我惊讶地发现 - 即使使用独立名称 __bar 也会发生这种情况。您从文档中发布的报价并没有真正明确地说明这一点。
  • @DanielRoseman:当一个标识符以文本形式出现在类定义中时这种转换独立于使用标识符的语法上下文。 这包括类主体中任何位置的标识符,包括方法定义。它是属性、全局还是本地都没有关系。

标签: python oop python-2.7 private


【解决方案1】:

在类定义中,所有以双下划线开始的名称都会被破坏;重写为包含类名作为前缀。

这是一个支持在类中将名称标记为“私有”并保护它不被子类覆盖的功能。见identifiers documentation

私有名称修改:当以文本形式出现在类定义中的标识符以两个或多个下划线字符开头并且不以两个或多个下划线结尾时,它被视为该类的私有名称.在为其生成代码之前,私有名称会转换为更长的形式。转换插入类名,删除前导下划线并在名称前面插入一个下划线。例如,出现在名为Ham 的类中的标识符__spam 将转换为_Ham__spam。这种转换与使用标识符的语法上下文无关。如果转换后的名称非常长(超过 255 个字符),则可能会发生实现定义的截断。如果类名仅包含下划线,则不进行任何转换。

最好不要在模块全局变量上使用双下划线前缀;没有必要这样做,一个下划线就足以表明该值是模块内部的。

如果您坚持使用这样的值,请创建一个未损坏的别名,或使用 globals()[name]

【讨论】:

  • 那么从类内部访问双分常数的最佳方法是什么? globals()['__bar'] 似乎有点 hacky。
  • @PauloBu:那个,或者使用sys.modules[__name__].__bar... 最好不要使用双下划线名称作为全局变量,真的。
  • 是的,我就是这么想的 :)
猜你喜欢
  • 1970-01-01
  • 2015-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多