class-private names and the Zen of Python

M

Marco Buttu

In the following case:
.... _Foo__a = 100
.... __a = 33
....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.
 
T

Terry Reedy

In the following case:

... _Foo__a = 100
... __a = 33
...
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.
 
M

Marco Buttu

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?
 
N

Ned Batchelder

In the following case:

... _Foo__a = 100
... __a = 33
...
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:
... a = 100
... a = 33
...33

Or for that matter:
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.
 
M

Marco Buttu

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

... a = 100
... a = 33
...
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...
 
S

Steven D'Aprano

In the following case:

... _Foo__a = 100
... __a = 33
...
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.
 
N

Ned Batchelder

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.
 
O

Oscar Benjamin

On Oct 8, 2013 2:26 PM, "Steven D&apos;Aprano" <
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
 
M

Marco Buttu

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
 
C

Charles Hixson

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.


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.


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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,037
Latest member
MozzGuardBugs

Latest Threads

Top