For review: PEP 308 - If-then-else expression

Bengt Richter bokr at oz.net
Mon Feb 10 03:48:46 EST 2003


On Sun, 9 Feb 2003 21:06:28 -0700, "Andrew Dalke" <adalke at mindspring.com> wrote:

>Carlos Ribeiro:
>> Then I wonder why do people think that the following snippet is pythonic
>in
>> any (reasonable) way:
>>
>>   ','.join(lines)
>>
>> In what direction does it reads?
>
>"Use a comma to join these lines"
>
>Still confusing, but I understand the reasons why.
>
>And in general, "obj.func(arg)" is "use this object to do this
>function to these arguments."
>
We might want to elaborate on how "this function" is found, though, and
the differences that arise depending on how it succeeds. E.g.,

 >>> class C:
 ...     def func(*args): print 'C.func args = %s' % `args`
 ...
 >>> def func(*args): print 'plain func args = %s' % `args`
 ...
 >>> func(123)
 plain func args = (123,)
 >>> c=C()
 >>> c.func(456)
 C.func args = (<__main__.C instance at 0x007A39E0>, 456)
 
What is that first parameter? It's the C instance c, normally bound to "self":
 >>> c
 <__main__.C instance at 0x007A39E0>

But it gets put there because of the way func was found. If we give
the instance a func attribute that stops the search from looking in
the class attributes and bases, the result may be different, e.g.,

 >>> c.func = func
 >>> c.func(789)
 plain func args = (789,)

It's an ordinary instance attribute name finding a plain function
and using it as such, so the c instance does not get passed to become
the "self" of a method.

We can undo the shadowing, and find the class attribute name 'func' again:
 >>> del c.func
 >>> c.func('a')
 C.func args = (<__main__.C instance at 0x007A39E0>, 'a')

This is also a dynamic effect, not dependent on having originally defined
func as a method of C. E.g., if we replace C.func with the plain func:

 >>> C.func = func
 >>> c.func('which func?')
 plain func args = (<__main__.C instance at 0x007A39E0>, 'which func?')
 ^^^^^^^^^^

You can see that the instance got passed as with the original func.
(it doesn't complain about the wrong number of args because of the *args
parameter spec).

And passing the instance to the class method C.func produces the same result
as getting it done for you when you use the attribute search via the instance:

 >>> c.func('which func?')
 plain func args = (<__main__.C instance at 0x007A39E0>, 'which func?')
 
 >>> C.func(c, 'which func?')
 plain func args = (<__main__.C instance at 0x007A39E0>, 'which func?')

Maybe this makes it easier to see how this applies when the class is str and
c is a str instance and func is join:

 >>> c = ','
 >>> c.join(['foo', 'bar'])
 'foo,bar'
 >>> str.join(c, ['foo', 'bar'])
 'foo,bar'

Regards,
Bengt Richter




More information about the Python-list mailing list