Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #56381 > unrolled thread

class-private names and the Zen of Python

Started byMarco Buttu <marco.buttu@gmail.com>
First post2013-10-08 12:13 +0200
Last post2013-10-09 12:34 -0700
Articles 10 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  class-private names and the Zen of Python Marco Buttu <marco.buttu@gmail.com> - 2013-10-08 12:13 +0200
    Re: class-private names and the Zen of Python Terry Reedy <tjreedy@udel.edu> - 2013-10-08 06:36 -0400
      Re: class-private names and the Zen of Python Marco Buttu <marco.buttu@gmail.com> - 2013-10-08 12:47 +0200
    Re: class-private names and the Zen of Python Ned Batchelder <ned@nedbatchelder.com> - 2013-10-08 07:07 -0400
      Re: class-private names and the Zen of Python Marco Buttu <marco.buttu@gmail.com> - 2013-10-08 13:15 +0200
        Re: class-private names and the Zen of Python Ned Batchelder <ned@nedbatchelder.com> - 2013-10-08 12:20 -0400
    Re: class-private names and the Zen of Python Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-10-08 13:24 +0000
      Re: class-private names and the Zen of Python Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-10-09 00:00 +0100
        Re: class-private names and the Zen of Python Marco Buttu <marco.buttu@gmail.com> - 2013-10-09 07:55 +0200
      Re: class-private names and the Zen of Python Charles Hixson <charleshixsn@earthlink.net> - 2013-10-09 12:34 -0700

#56381 — class-private names and the Zen of Python

FromMarco Buttu <marco.buttu@gmail.com>
Date2013-10-08 12:13 +0200
Subjectclass-private names and the Zen of Python
Message-ID<l30lsq$tfd$1@speranza.aioe.org>
In the following case:

 >>> class Foo:
...     _Foo__a = 100
...     __a = 33
...
 >>> Foo._Foo__a
33

I think this behavior, for a user who does not know the convention, 
could be a surprise. Should be raising an exception (in order to inform 
the user the transformation of the name __a have been replaced an 
existing name) a possible --explicit-- alternative?

Another question is: where is the place in which this transformation 
occurs? Is it at the parser level, before the dictionary attribute is 
gave as argument to the metaclass?

I looked at the documentation:

http://docs.python.org/3/reference/lexical_analysis.html
http://docs.python.org/3/reference/expressions.html#atom-identifiers

but it is not clear when this transformation happens.

-- 
Marco Buttu

[toc] | [next] | [standalone]


#56384

FromTerry Reedy <tjreedy@udel.edu>
Date2013-10-08 06:36 -0400
Message-ID<mailman.848.1381228611.18130.python-list@python.org>
In reply to#56381
On 10/8/2013 6:13 AM, Marco Buttu wrote:
> In the following case:
>
>  >>> class Foo:
> ...     _Foo__a = 100
> ...     __a = 33
> ...
>  >>> Foo._Foo__a
> 33
>
> I think this behavior, for a user who does not know the convention,
> could be a surprise.

No one qualified to use such names would do such a thing , so there is 
no need to worry about it or do anything about it.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#56385

FromMarco Buttu <marco.buttu@gmail.com>
Date2013-10-08 12:47 +0200
Message-ID<5253E2B5.4060905@gmail.com>
In reply to#56384
On 10/08/2013 12:36 PM, Terry Reedy wrote:

> On 10/8/2013 6:13 AM, Marco Buttu wrote:
>> In the following case:
>>
>>  >>> class Foo:
>> ...     _Foo__a = 100
>> ...     __a = 33
>> ...
>>  >>> Foo._Foo__a
>> 33
>>
>> I think this behavior, for a user who does not know the convention,
>> could be a surprise.
>
> No one qualified to use such names would do such a thing , so there is
> no need to worry about it or do anything about it.

Is this transformation performed by the parser, before to call the 
metaclass?

-- 
Marco Buttu

[toc] | [prev] | [next] | [standalone]


#56386

FromNed Batchelder <ned@nedbatchelder.com>
Date2013-10-08 07:07 -0400
Message-ID<mailman.849.1381230484.18130.python-list@python.org>
In reply to#56381
On 10/8/13 6:13 AM, Marco Buttu wrote:
> In the following case:
>
> >>> class Foo:
> ...     _Foo__a = 100
> ...     __a = 33
> ...
> >>> Foo._Foo__a
> 33
>
> I think this behavior, for a user who does not know the convention, 
> could be a surprise. Should be raising an exception (in order to 
> inform the user the transformation of the name __a have been replaced 
> an existing name) a possible --explicit-- alternative? 

You also get a "problem" if you do this:

     >>> class Foo:
    ...     a = 100
    ...     a = 33
    ...
     >>> Foo.a
    33

Or for that matter:

     >>> a = 100
     >>> a = 33
     >>> a
    33

There are lots of ways to change what value a name refers to, it's not 
an error to reassign names.

Also, as Terry mentions, no one has ever assigned the two names you 
show, so why try to warn about it?

--Ned.

[toc] | [prev] | [next] | [standalone]


#56388

FromMarco Buttu <marco.buttu@gmail.com>
Date2013-10-08 13:15 +0200
Message-ID<5253E945.5030608@gmail.com>
In reply to#56386
On 10/08/2013 01:07 PM, Ned Batchelder wrote:

> On 10/8/13 6:13 AM, Marco Buttu wrote:
>>
>> >>> class Foo:
>> ...     _Foo__a = 100
>> ...     __a = 33
>> ...
>> >>> Foo._Foo__a
>> 33
>>
...
> You also get a "problem" if you do this:
>
>      >>> class Foo:
>     ...     a = 100
>     ...     a = 33
>     ...
>      >>> Foo.a
>     33

But this does not happen under the hood, it is explicit

> Also, as Terry mentions, no one has ever assigned the two names you
> show,

Sincerely, I can not now if someone has assigned (or will assegne) in 
such way...

-- 
Marco Buttu

[toc] | [prev] | [next] | [standalone]


#56430

FromNed Batchelder <ned@nedbatchelder.com>
Date2013-10-08 12:20 -0400
Message-ID<mailman.866.1381250555.18130.python-list@python.org>
In reply to#56388
On 10/8/13 7:15 AM, Marco Buttu wrote:
>
>> Also, as Terry mentions, no one has ever assigned the two names you
>> show,
>
> Sincerely, I can not now if someone has assigned (or will assegne) in 
> such way...

If you explain more about what you are building, and where this crops up 
as a problem, we can help come up with a solution.

--Ned.

[toc] | [prev] | [next] | [standalone]


#56395

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-10-08 13:24 +0000
Message-ID<52540779$0$29984$c3e8da3$5496439d@news.astraweb.com>
In reply to#56381
On Tue, 08 Oct 2013 12:13:48 +0200, Marco Buttu wrote:

> In the following case:
> 
>  >>> class Foo:
> ...     _Foo__a = 100
> ...     __a = 33
> ...
>  >>> Foo._Foo__a
> 33
> 
> I think this behavior, for a user who does not know the convention,
> could be a surprise. 

Yes, you are correct. It surprised me, and I've been using Python for 
more than 15 years, and I know the convention of double-underscore name-
mangling.


> Should be raising an exception (in order to inform
> the user the transformation of the name __a have been replaced an
> existing name) a possible --explicit-- alternative?

No, I don't think so. That would slow down class creation, for no real 
benefit. Except for the name-mangling part, this is no different from:

class Spam:
    x = 23
    x = 42

If anything, something like PyLint or PyChecker could warn about it. But 
the language itself is fine like it is.


> Another question is: where is the place in which this transformation
> occurs? Is it at the parser level, before the dictionary attribute is
> gave as argument to the metaclass?

Good question!

I don't have a full answer, but I have a part answer: it occurs before 
the metaclass sees the namespace:

py> class Meta(type):
...     def __new__(meta, name, bases, namespace):
...             print(namespace)
...             return super().__new__(meta, name, bases, namespace)
...
py>
py> class Test(metaclass=Meta):
...     __test = 'foo'
...
{'__module__': '__main__', '_Test__test': 'foo', '__qualname__': 'Test'}


so I think it is done by the parser.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#56453

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2013-10-09 00:00 +0100
Message-ID<mailman.880.1381273223.18130.python-list@python.org>
In reply to#56395

[Multipart message — attachments visible in raw view] — view raw

On Oct 8, 2013 2:26 PM, "Steven D&apos;Aprano" <
steve+comp.lang.python@pearwood.info> wrote:
>
> On Tue, 08 Oct 2013 12:13:48 +0200, Marco Buttu wrote:
>
> > Another question is: where is the place in which this transformation
> > occurs? Is it at the parser level, before the dictionary attribute is
> > gave as argument to the metaclass?
>
> Good question!
>
> I don't have a full answer, but I have a part answer: it occurs before
> the metaclass sees the namespace:
>

I thought it was at the parser level and applied to assignments at class
level and attribute assignments anywhere within a class body.

I'm pretty sure there's no way to control the behaviour from Python code if
that's what the metaclass question is getting at.

Oscar

[toc] | [prev] | [next] | [standalone]


#56468

FromMarco Buttu <marco.buttu@gmail.com>
Date2013-10-09 07:55 +0200
Message-ID<l32r50$o2r$1@speranza.aioe.org>
In reply to#56453
On 10/09/2013 01:00 AM, Oscar Benjamin wrote:

>  > On Tue, 08 Oct 2013 12:13:48 +0200, Marco Buttu wrote:
>  >
>  > > Another question is: where is the place in which this transformation
>  > > occurs? Is it at the parser level, before the dictionary attribute is
>  > > gave as argument to the metaclass?
>
> I thought it was at the parser level and applied to assignments at class
> level and attribute assignments anywhere within a class body.
>
> I'm pretty sure there's no way to control the behaviour from Python code
> if that's what the metaclass question is getting at.
>
> Oscar

Thanks for the clear and exhaustive answers (from you and Steven).
I was looking for a way to change the default behavior of this 
transformation (just for playing a bit with metaclasses, nothing 
serious), with snippets of code like the one of Steven (by rewriting 
__new__), but now is clear there is no way to do this with metaclasses. 
Thanks again


-- 
Marco Buttu

[toc] | [prev] | [next] | [standalone]


#56513

FromCharles Hixson <charleshixsn@earthlink.net>
Date2013-10-09 12:34 -0700
Message-ID<mailman.905.1381347542.18130.python-list@python.org>
In reply to#56395
On 10/08/2013 06:24 AM, Steven D'Aprano wrote:
> On Tue, 08 Oct 2013 12:13:48 +0200, Marco Buttu wrote:
>
>> In the following case:
>>
>>   >>> class Foo:
>> ...     _Foo__a = 100
>> ...     __a = 33
>> ...
>>   >>> Foo._Foo__a
>> 33
>>
>> I think this behavior, for a user who does not know the convention,
>> could be a surprise.
> Yes, you are correct. It surprised me, and I've been using Python for
> more than 15 years, and I know the convention of double-underscore name-
> mangling.
>
>
>> Should be raising an exception (in order to inform
>> the user the transformation of the name __a have been replaced an
>> existing name) a possible --explicit-- alternative?
> No, I don't think so. That would slow down class creation, for no real
> benefit. Except for the name-mangling part, this is no different from:
>
> class Spam:
>      x = 23
>      x = 42
>
> If anything, something like PyLint or PyChecker could warn about it. But
> the language itself is fine like it is.
>
>
>> Another question is: where is the place in which this transformation
>> occurs? Is it at the parser level, before the dictionary attribute is
>> gave as argument to the metaclass?
> Good question!
>
> I don't have a full answer, but I have a part answer: it occurs before
> the metaclass sees the namespace:
>
> py> class Meta(type):
> ...     def __new__(meta, name, bases, namespace):
> ...             print(namespace)
> ...             return super().__new__(meta, name, bases, namespace)
> ...
> py>
> py> class Test(metaclass=Meta):
> ...     __test = 'foo'
> ...
> {'__module__': '__main__', '_Test__test': 'foo', '__qualname__': 'Test'}
>
>
> so I think it is done by the parser.
Unless one wanted to add an error checking mode to the interpreter, not 
a totally bad idea, I agree that this is a job for external tools.  But 
perhaps that same external tool should be referenced in the 
documentation.  As it is I'm not clear that PyLint and/or PyChecker are 
kept current with the compiler/interpreter version, and I rather suspect 
that they aren't.  (This won't normally show up, as changes that they 
would catch happen quite rarely, but...)

OTOH, neither one really fits in as, say, an included module...they're 
more like idle, which now that I look does have a "check module" run 
option.  Perhaps that invokes one of them.  I note that Idle, itself, is 
barely mentioned in the documentation. Perhaps there needs to be a 
"tools" section.


-- 
Charles Hixson

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web