This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Double underscore variables in module are mangled when used in class
Type: behavior Stage: resolved
Components: Versions: Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: avraf, con-f-use, r.david.murray
Priority: normal Keywords:

Created on 2016-08-18 12:27 by avraf, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (6)
msg273023 - (view) Author: (avraf) Date: 2016-08-18 12:27
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 <module>
    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
msg273032 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-08-18 14:36
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.
msg363393 - (view) Author: Jan Christoph (con-f-use) * Date: 2020-03-04 22:12
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
msg363395 - (view) Author: Jan Christoph (con-f-use) * Date: 2020-03-04 22:16
Just because it is documented, doesn't mean it's not a bug or illogical and unexpected.
msg363553 - (view) Author: Jan Christoph (con-f-use) * Date: 2020-03-06 21:10
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.
msg363559 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2020-03-06 21:40
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.
History
Date User Action Args
2022-04-11 14:58:35adminsetgithub: 71980
2020-03-06 21:40:27r.david.murraysetmessages: + msg363559
2020-03-06 21:10:21con-f-usesetmessages: + msg363553
2020-03-04 22:16:00con-f-usesetmessages: + msg363395
2020-03-04 22:12:57con-f-usesetnosy: + con-f-use
messages: + msg363393
2016-08-18 14:36:25r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg273032

resolution: not a bug
stage: resolved
2016-08-18 12:27:25avrafcreate