Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #101370 > unrolled thread
| Started by | Joseph Fox-Rabinovitz <jfoxrabinovitz@gmail.com> |
|---|---|
| First post | 2016-01-07 11:14 -0500 |
| Last post | 2016-01-09 12:25 +1100 |
| Articles | 4 — 3 participants |
Back to article view | Back to comp.lang.python
Unable to access module attribute with underscores in class method, Python 3 Joseph Fox-Rabinovitz <jfoxrabinovitz@gmail.com> - 2016-01-07 11:14 -0500
Re: Unable to access module attribute with underscores in class method, Python 3 Steven D'Aprano <steve@pearwood.info> - 2016-01-09 03:07 +1100
Re: Unable to access module attribute with underscores in class method, Python 3 Chris Angelico <rosuav@gmail.com> - 2016-01-09 03:16 +1100
Re: Unable to access module attribute with underscores in class method, Python 3 Steven D'Aprano <steve@pearwood.info> - 2016-01-09 12:25 +1100
| From | Joseph Fox-Rabinovitz <jfoxrabinovitz@gmail.com> |
|---|---|
| Date | 2016-01-07 11:14 -0500 |
| Subject | Unable to access module attribute with underscores in class method, Python 3 |
| Message-ID | <mailman.62.1452258624.2305.python-list@python.org> |
Hi,
I have a module attribute whose name starts with a pair of underscores. I
am apparently unable to access it directly in a class method (within the
same module, but that is not relevant as far as I can tell). The following
bit of code illustrates the situation:
__a = 3
class B:
def __init__(self):
global __a
self.a = __a
b = B()
This results in a NameError because of name-mangling, despite the global
declaration:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NameError: name '_B__a' is not defined
Not using global does not make a difference. I posted a similar question on
Stack Overflow, where the only reasonable answer given was to wrap __a in a
container whose name is not mangled. For example, doing `self.a =
globals()['__a']` or manually creating a dictionary with a non-mangled name
and accessing that.
I feel that there should be some way of accessing __a within the class
directly in Python 3. Clearly my expectation that global would fix the
issue is incorrect. I would appreciate either a solution or an explanation
of what is going on that would convince me that accessing a module
attribute in such a way should be forbidden.
-Joseph Fox-Rabinovitz
P.S. For reference, the Stack Overflow question is here:
http://stackoverflow.com/questions/34621484/how-to-access-private-variable-of-python-module-from-class
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2016-01-09 03:07 +1100 |
| Message-ID | <568fded7$0$1608$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #101370 |
On Fri, 8 Jan 2016 03:14 am, Joseph Fox-Rabinovitz wrote:
> Hi,
>
> I have a module attribute whose name starts with a pair of underscores.
Don't do that.
The way to flag a module-level variable as private is with a single leading
underscore. Double-leading underscores are intended for use in classes, to
be name-mangled, and double-leading-and-trailing underscores are reserved
for use by Python.
> I am apparently unable to access it directly in a class method (within the
> same module, but that is not relevant as far as I can tell). The following
> bit of code illustrates the situation:
>
> __a = 3
> class B:
> def __init__(self):
> global __a
> self.a = __a
> b = B()
>
> This results in a NameError because of name-mangling, despite the global
> declaration:
The global declaration is name-mangled as well, as can be seen from the
byte-code:
py> from dis import dis
py> class Test:
... def method(self):
... global __a
... x = __a
...
py> dis(Test.method)
4 0 LOAD_GLOBAL 0 (_Test__a)
3 STORE_FAST 1 (x)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
That's exactly as described: within a class, ALL references to
double-leading underscore names are mangled.
> Not using global does not make a difference. I posted a similar question
> on Stack Overflow, where the only reasonable answer given was to wrap __a
> in a container whose name is not mangled.
That's not a reasonable answer. That's adding unreasonable complication to
the code, just to support an unreasonable global name.
> For example, doing `self.a =
> globals()['__a']` or manually creating a dictionary with a non-mangled
> name and accessing that.
>
> I feel that there should be some way of accessing __a within the class
> directly in Python 3. Clearly my expectation that global would fix the
> issue is incorrect. I would appreciate either a solution or an explanation
> of what is going on that would convince me that accessing a module
> attribute in such a way should be forbidden.
You are trying to fight the language. __names are intended for a specific
use in Python, and you're ignoring that and trying to use them for
something else. That's fine so long as your use and the intended use don't
clash, but if they do clash (as they are here) then there's only one
reasonable answer: stop abusing name-mangled names.
If you absolutely insist that you must must must continue to use a double
underscore name, you could also try this:
py> __a = 1
py> class Test:
... def method(self):
... x = eval("__a")
... print(x)
...
py> Test().method()
1
But don't do that.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-01-09 03:16 +1100 |
| Message-ID | <mailman.74.1452269803.2305.python-list@python.org> |
| In reply to | #101381 |
On Sat, Jan 9, 2016 at 3:07 AM, Steven D'Aprano <steve@pearwood.info> wrote:
> If you absolutely insist that you must must must continue to use a double
> underscore name, you could also try this:
>
> py> __a = 1
> py> class Test:
> ... def method(self):
> ... x = eval("__a")
> ... print(x)
> ...
> py> Test().method()
> 1
>
>
> But don't do that.
Seriously? You consider that less bad than globals()["__a"]?
But all of this is craziness to support craziness. It's not asking
which inmate should run the asylum - it's asking which of my multiple
personalities should be elected fourteen-year-old queen.
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2016-01-09 12:25 +1100 |
| Message-ID | <5690617b$0$1583$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #101382 |
On Sat, 9 Jan 2016 03:16 am, Chris Angelico wrote:
> On Sat, Jan 9, 2016 at 3:07 AM, Steven D'Aprano <steve@pearwood.info>
> wrote:
>> If you absolutely insist that you must must must continue to use a double
>> underscore name, you could also try this:
>>
>> py> __a = 1
>> py> class Test:
>> ... def method(self):
>> ... x = eval("__a")
>> ... print(x)
>> ...
>> py> Test().method()
>> 1
>>
>>
>> But don't do that.
>
> Seriously? You consider that less bad than globals()["__a"]?
No. That's why I said "don't do that" rather than "you should do this" :-)
> But all of this is craziness to support craziness. It's not asking
> which inmate should run the asylum - it's asking which of my multiple
> personalities should be elected fourteen-year-old queen.
Loretta, surely.
--
Steven
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web