Attack a sacred Python Cow

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Sun Jul 27 21:39:26 CEST 2008


Derek Martin a écrit :
> On Sun, Jul 27, 2008 at 08:19:17AM +0000, Steven D'Aprano wrote:
>>> You take the name down to a single letter. As I suggested in an earlier
>>> post on this thread, why not take it down to zero letters? 
>> The question isn't "why not", but "why". The status quo works well as it 
>> is, even if it isn't perfect. Prove that implicit self is a good idea -- 
>> or at least prove that it is an idea worth considering.
> 
> Come on, this sounds like a schoolyard argument.  This comes down to a
> matter of style, and as such, is impossible to prove.  It's largely a
> question of individual preference.
> 
> That said, the argument in favor is rather simple:
> 
> 1. This is an extremely common idiom in Python
> 2. It is completely unnecessary, and the language does not suffer for
>    making it implicit
> 3. Making it implicit reduces typing, reduces opportunities for
>    mistakes, and arguably increases consistency.

"arguably", indeed, cf below.

> As for the latter part of #3, self (or some other variable) is
> required in the parameter list of object methods,

It's actually the parameter list of the *function* that is used as the 
implementation of a method. Not quite the same thing. And then, 
consistency mandates that the target object of the method is part of the 
parameter list of the *function*, since that's how you make objects 
availables to a function.

> however when the
> method is *called*, it is omitted.

Certainly not. You need to lookup the corresponding attribute *on a 
given object* to get the method. Whether you write

   some_object.some_method()

or

   some_function(some_object)

you still need to explicitely mention some_object.


> It is implied, supplied by Python.

Neither. The target object is passed to the function by the method 
object, which is itself returned by the __get__ method of function 
objects, which is one possible application of the more general 
descriptor protocol (the same protocol that is used for computed 
attributes). IOW, there's nothing specific to 'methods' here, just the 
use of two general features (functions and the descriptor protocol). 
FWIW, you can write your own callable, and write it so it behave just 
like a function here:

import types

class MyCallable(object):
    def __call__(self, obj):
        print "calling %s with %s" % (self, obj)
    def __get__(self, instance, cls):
        return types.MethodType(self.__call__, instance, cls)

class Foo(object):
     bar = MyCallable()

print Foo.bar
f = Foo()
f.bar()

> Thus when an object method is called, it must be called with one fewer
> arguments than those which are defined.   This can be confusing,
> especially to new programmers.

This is confusing as long as you insist on saying that what you 
"def"ined is a method - which is not the case.

> It can also be argued that it makes the code less ugly, though again,
> that's a matter of preference.
> 
>> It's not enough to show that a change "isn't bad" -- you have to show 
>> that it is actively good. 
> 
> But he did... he pointed out that *it saves work*, without actually
> being bad.  Benefit, without drawback.  Sounds good to me!
> 
>> "Don't need to look at the method signature" is not an argument in favour 
>> of implicit self. 
> 
> Yes, actually, it is.

It isn't, since there's no "method signature" to look at !-)

>  If there is a well-defined feature of Python
> which provides access to the object within itself,

The point is that you don't get access to the object "within itself". 
You get access to an object *within a function*.

The fact that a function is defined within a class statement doesn't 
imply any "magic", it just creates a function object, bind it to a name, 
and make that object an attribute of the class. You have the very same 
result by defining the function outside the class statement and binding 
it within the class statement, by defining the function outside the 
class and binding it to the class outside the class statement, by 
binding the name to a lambda within the class statement etc...

> then the
> opportunities for mistakes when someone decides to use something else
> are lessened.
> 
>> You don't need to look at the method signature when you're using an
>> explicit self either.
> 
> That isn't necessarily true.  If you're using someone else's code, and
> they didn't use "self" -- or worse yet, if they chose this variable's
> name randomly throughout their classes -- then you may well need to
> look back to see what was used.
> 
> It's bad programming, but the world is full of bad programmers, and we
> don't always have the choice not to use their code.  Isn't one of
> Python's goals to minimize opportunities for bad programming?

Nope. That's Java's goal. Python's goals are to maximize opportunities 
for good programming, which is quite different.

> Providing a keyword equivalent to self and removing the need to name
> it in object methods is one way to do that.

It's also a way to make Python more complicated than it needs to be. At 
least with the current state, you define your functions the same way 
regardless of how they are defined, and the implementation is 
(relatively) easy to explain. Special-casing functions definition that 
happens within a class statement would only introduce a special case. 
Then you'd have to explain why you need to specify the target object in 
the function's parameters when the function is defined outside the class 
but not when it's defined within the class.

IOW : there's one arguably good reason to drop the target object from 
functions used as methods implementation, which is to make Python looks 
more like Java, and there's at least two good reason to keep it the way 
it is, which are simplicity (no special case) and consistency (no 
special case).

Anyway, the BDFL has the final word, and it looks like he's not going to 
change anything here - but anyone is free to propose a PEP, isn't it ?



More information about the Python-list mailing list