Arithmetic sequences in Python

Bengt Richter bokr at oz.net
Tue Jan 24 00:02:29 EST 2006


On Mon, 23 Jan 2006 21:43:16 +1100, Steven D'Aprano <steve at REMOVETHIScyber.com.au> wrote:

>On Sun, 22 Jan 2006 16:40:48 -0800, Paul Rubin wrote:
>
>> Steve Holden <steve at holdenweb.com> writes:
>>> > The current list function is supposed to be something like a
>>> > typecast:
>>> >
>>> list() isn't a function, it's a type.
>> 
>> I'm not sure what the distinction is supposed to be.  "list" is anyway
>> callable, and lambda a:list(a) is certainly a function. 
>
>
>class Parrot:
>    def __init__(self):
>        pass
>
>Parrot is callable. Is it a function?
>
No. It is an object that inherits a __call__ method that makes it callable with a (<args>) source syntax trailer
in a similar way to an object created with a def (which is a function in python convention, and which
also inherits a __call__ method), but the similarity does not make Parrot a function:

 >>> class Parrot:
 ...     def __init__(self):
 ...         pass
 ...
(BTW you could have inherited a do-nothing __init__ ;-)

 >>> type(Parrot).mro()
 [<type 'classobj'>, <type 'object'>]
 >>> type(Parrot).mro()[0].__call__
 <slot wrapper '__call__' of 'classobj' objects>
Or, showing more explicitly where it comes from:
 >>> type(Parrot).mro()[0].__dict__['__call__']
 <slot wrapper '__call__' of 'classobj' objects>

Invoked:
 >>> type(Parrot).mro()[0].__dict__['__call__'](Parrot)
 <__main__.Parrot instance at 0x02EF340C>

Hm, actually that is like calling the im_func of the unbound method of a newstyle class ...
I think maybe actually Parrot() causes

 >>> type(Parrot).mro()[0].__dict__['__call__'].__get__(Parrot, type(Parrot))()
 <__main__.Parrot instance at 0x02EF398C>

A function is also an object with a __call__ method. E.g., compare above the line with
calling foo (after definition just below) the long way:

 >>> def foo(): return 'returned by foo'
 ...
 >>> type(foo).mro()[0].__dict__['__call__'].__get__(foo, type(foo))()
 'returned by foo'

Playing with that a little:
 >>> type(foo).mro()
 [<type 'function'>, <type 'object'>]
 >>> type(foo).mro()[0]
 <type 'function'>
 >>> type(foo).mro()[0].__call__
 <slot wrapper '__call__' of 'function' objects>
 >>> type(foo).mro()[0].__call__(foo)
 'returned by foo'
 >>> foo.__call__
 <method-wrapper object at 0x02EF340C>
 >>> foo.__call__()
 'returned by foo'
 >>> type(foo).mro()[0].__call__.__get__
 <method-wrapper object at 0x02EF340C>
 >>> type(foo).mro()[0].__call__.__get__(foo, type(foo))
 <method-wrapper object at 0x02EF39AC>
 >>> type(foo).mro()[0].__call__.__get__(foo, type(foo))()
 'returned by foo'
or
 >>> foo()
 'returned by foo'

>
>Types are types, classes are classes, functions are functions.
classes seem to be classobjs, designed to implement classic class behavior
but using the new machinery to achieve compatible integration.

>
>Admittedly I still confused between the various flavours of functions
>(function, bound method, unbound method, class method, static method...)
>*wink* but the difference between types and functions is fairly clear.
>
>Just don't ask about the difference between type and class... *wink*
>
Why not? ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list