Accesing private module variable from class

2020-02-29 11:32发布

问题:

I'm trying understand python scope rules. To do this I try access "very private" variable from class in same module

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()

It fails with NameError. I can't find anything about that in specification. So, why it fails and where this behavior described?

回答1:

Within a class definition, all names starting with double underscores are mangled; rewritten to include the class name as a prefix.

This is a feature to support marking names as 'private' within the class and protect it against being overwritten by subclasses. See the identifiers documentation:

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. If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done.

Best not use double-underscore prefixes on module globals; there is no need to do so, a single underscore is enough to communicate that the value is internal to the module.

If you are stuck with such a value, create an alias that isn't mangled, or use globals()[name].