PEP 318: Can't we all just get along?

Paul Morrow pm_mon at yahoo.com
Fri Aug 20 14:35:24 CEST 2004


Anthony Baxter wrote:

> On Fri, 20 Aug 2004 05:57:42 -0400, Paul Morrow <pm_mon at yahoo.com> wrote:
> 
>>I know you weren't Anthony (that was a joke).  I understand that you
>>don't like this idea, but that doesn't make it a _bad_ one. Numerous
>>people have *not* effectively pointed out the problems with it (and
>>neither have you, sir).
> 
> 
> Err, what? Have you bothered to read the replies I sent to you? 

Yes of course I have.  You can tell because I've replied to everything 
you've said, directly (as best I could) addressing your 'points'.  Have 
you noticed my replies?  Did you bother to read them?

> This is _bad_ magic behaviour. Python does not care about argument lists
> now, and adding this is icky. 

Python doesn't do this now.  Check.  You think that it's "icky".  Check.

> Your behaviour when _adding_ methods to classes is extremely undefined, 
> particularly in the presence of 
> descriptors. 

If you're talking about dynamically adding methods to classes (at 
runtime), we've discussed this in general.  You have to have the first 
parm name correct before you add the method.

But we haven't talked about descriptor issues yet, have we?  What's the 
problem with them?

> Explaining this to new users would be complex. 

We discussed this before too (didn't we?).  It will be *less* complex 
for new users.  Well, you tell me.  Here's the only part of the 
classmethod documentation that would change (from 
http://docs.python.org/lib/built-in-funcs.html)...

"""
A class method receives the class as implicit first argument, just like 
an instance method receives the instance. To declare a class method, use 
this idiom:

class C:
     def f(cls, arg1, arg2, ...): ...
     f = classmethod(f)
"""

...it would be changed to (something like) this...

"""
A class method receives the class as its first argument 'cls', just like 
an instance method receives the instance as its first argument 'self'. 
To declare a class method, use this idiom:

class C:
     def f(cls, arg1, arg2, ...): ...

Note that the first argument of each class method must be named 'cls'.
"""


> It's a
> messy interference in the way Python's OO builds classes and objects,
> which is currently very clear and easy to follow[1]. 

We haven't discussed this, have we?  What do you mean?


> It's not explicit, but implicit.

True.  But then so is dynamic typing, a powerful feature of Python that 
differentiates it from languages like Java, C++.  Therefore, you aren't 
saying enough here for that point to be valid.


> How many ways do I have to spell this out?  

One valid spelling would be a good start.


> 
> The only argument _for_ this that you've offered is that it's just like the
> double-underscores. 

Oh my... <sigh>  Have you been reading *my* posts?  If so, I must be 
doing a terrible job of communicating here (my apologies).  Here are 
four reasons in favor of it.  Rip them apart to your satisfaction.

1. It make formal a convention widely used by others and therefore would 
have an obvious interpretation to readers of your code.

2. It doesn't require as much typing as the current technique nor any 
proposed decorator technique.

3. It is less error prone (because it is WYSIWYG) than the current 
technique.

4. It is easier to understand than the current technique.


> double-underscores. This is a losing argument (with me, anyway) as
> I regard the double-underscore mangling as awful - that sort of "data
> hiding" just ends up being a pain in the arse when you want to poke 
> with a class's internals. Python regards everyone as an adult in that 
> respect, unlike the "protecting you from yourself" C++ nightmare. In
> addition, the double-underscore is just random magic that occurs when
> a class is created, not subsequently:
> 
> 
>>>>class A:
> 
> ...   __foo = 1
> ... 
> 
>>>>dir(A)
> 
> ['_A__foo', '__doc__', '__module__']
> 
>>>>A.__bar = 2
>>>>dir(A)
> 
> ['_A__foo', '__bar', '__doc__', '__module__']
> 
> for the same reasons, your idea would lead to inconsistencies.
>

That's an interesting point.  The behavior you illustrate is apparently 
a Python bug wrt private attributes.  If it was consistent...

    A.__bar = 2

would work, but a subsequent

    print A.__bar

would generate an attribute error.

But of course its easy to make Python work that way (as I show below). 
Likewise, I'm sure similar inconsistencies in 'my' (for lack of a better 
word --- I didn't actually come up with it) idea could be as easily 
resolved.

#############################################################
class M(type):
     def __setattr__(metacls, attrName, value):
         if attrName.startswith('__'):
             attrName = '_%s%s' % (metacls.__name__, attrName)
         type.__setattr__(metacls, attrName, value)

class A:
     __metaclass__ = M
     __foo = 1

print [x for x in dir(A) if x.startswith('_A')]   # 1.
A.__bar = 2
print [x for x in dir(A) if x.startswith('_A')]   # 2.

"""Footnotes:
     1. prints ['_A__foo']
     2. prints ['_A__bar', '_A__foo']
"""
#############################################################





More information about the Python-list mailing list