import re __no_spaces_pattern = r'\S+' __match_chars_until_space = re.compile(__no_spaces_pattern).match __match_chars_from_last_space = re.compile(__no_spaces_pattern + '$').match def __get_chars_until_space(name): return __match_chars_until_space(name).group() def __get_chars_from_last_space(name): return __match_chars_from_last_space(name).group() __random_unique_five_digit_number = 12345 __random_id_generator = lambda: __random_unique_five_digit_number class Person(object): def __init__(self, name): self.name = name @property def first_name(self): return __get_chars_until_space(self.name) @property def last_name(self): return __get_chars_from_last_space(self.name) I get this error when importing and running in another file. It seems python mangles every occurrence of double underscores seen in a class. Even if the double underscores variable appears in the body of a method and belongs to the module. This behavior is very unexpected. Traceback (most recent call last): File "beef.py", line 5, in print bob.first_name File "/home/dude/style/static_private_methods/real_static_private_functions.py", line 22, in first_name return __get_chars_until_space(self.name) NameError: global name '_Person__get_chars_until_space' is not defined
This is working as designed (https://docs.python.org/3/tutorial/classes.html#private-variables): "This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class." If you want to advocate changing that you'll have to start a thread on python-ideas, but I don't think the benefit would be worth the cost.
I would argue to reopen this. Seeing I and other people run into that issue (e.g. https://stackoverflow.com/q/40883083/789308) quiet frequently. Especially since it breaks the `global` keyword, e.g.: __superprivate = "mahog" class AClass(object): def __init__(self, value): global __superprivate __superprivate = value @staticmethod def get_sp(): return __superprivate if __name__ == "__main__": print(__superprivate) # mahog try: print(AClass.get_sp()) except NameError as e: print(e) # NameError: name '_AClass__superprivate' is not defined' cl = AClass("bla") print(cl.get_sp()) # bla __superprivate = 1 print(cl.get_sp()) # bla print(AClass.get_sp()) # bla
In particular, this might conflict with the documentation of global, which states: > If the target is an identifier (name): > > If the name does not occur in a global statement in the current code block: the name is bound to the object in the current local namespace. > > Otherwise: the name is bound to the object in the current global namespace. There is no exception of names that are within the body of a class object and start (but not end) with double underscores.
You are welcome to open a doc-enhancement issue for the global docs. For the other, as noted already if you want to advocate for a change to this behavior you need to start on python-ideas, but I don't think you will get any traction. Another possible enhancement you could propose (in a new issue) is to have the global statement check for variables that start with '__' and do something appropriate such as issue a warning...although I don't really know how hard that would be to implement.