Marc
Marc

Reputation: 3313

Referring to outer scope from python class

I have a (simplified) module, something like this:

import tkinter as tk

__outerVar = {<dict stuff>}

class Editor(tk.Frame):
...
    def _insideFunction(self):
        for p in __outerVar.keys():
            <do stuff>

I'm getting a NameError: name '_Editor__outerVar' is not defined on the use of __outerVar when I try to instantiate Editor. I tried putting "global __outerVar" at the top of insideFunction, even though I'm not writing to __outerVar, same error.

I'm sure I'm just misunderstanding some python scope rule here. Help?

py 3.5

Upvotes: 1

Views: 338

Answers (2)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160447

Python replaces any names preceded by a double underscore __ in order to simulate 'private attributes'. In essence __name becomes _classname__name. This, called name mangling, happens only within classes as documented in the docs:

This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

The solution is don't use __name names, using something like _name or just name suffices.

As an addendum, in PEP 8 -- Method Names and Instance Variables it states:

Python mangles these names with the class name: if class Foo has an attribute named __a , it cannot be accessed by Foo.__a . (An insistent user could still gain access by calling Foo._Foo__a.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.

So, unless you're designing for cases were subclass name clashing might be issue, don't use double leading underscores.

Upvotes: 3

mgilson
mgilson

Reputation: 309929

You're seeing name mangling in effect. From the documentation:

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

As far as I can think, the only way around this is to rename the __outerVar in the global scope to something that doesn't start with double underscores.

Upvotes: 3

Related Questions