473,509 Members | 3,039 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Impossible to change methods with special names of instances ofnew-style classes?

Hi python-list,

I've just started using new-style classes and am a bit confused as to
why I can't seem to alter methods with special names
(__call__, etc.) of new-style class instances. In other words, I
can do this:
>>class Z:
.... pass
....
>>z = Z()
z.__call__ = lambda : 33
z()
33

But apparently I can't do this:
>>class NZ(object):
.... pass
....
>>nz = NZ()
nz.__call__ = lambda : 33
nz()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NZ' object is not callable
I found this post from Bengt Richter three years ago which addressed a
related problem:

http://mail.python.org/pipermail/pyt...ly/332961.html
>Apparently the issue, as stated implicitly or explicitly by most of
you, is that new-style class instances essentially defer their magic
methods to the class's static versions of same. This is good to know :)
Actually, it's not just the "magic" methods. If you have an
instance a of a newstyle class A, any attribute lookup a.attr will
undergo the same search first to see if attr is a descriptor
object, and if not, *then* to look in the instance attribute
directory. But the descriptor search doesn't start in
inst.__dict__, it goes through the chain of classes and base
classes provided by type(inst).mro(), which starts in
type(inst). And for our class A instance a, type(a) will be A, so
the search for a.attr starts there. Same applies to a.__str__. This
ensures that all instances of the same class will share the same
methods. The way a method, which is just a class variable with a
function as its value, gets to be a callable bound method, is the
same as any attribute lookup looking for a descriptor with a
__get__ method (which a function also has, for this purpose). If
the descriptor doesn't have a __set__ method as well, then an
instance attribute takes priority. If there is a __set__ method,
and instance attribute can't shadow the attribute name, and the
descriptor __get__ method takes precedence. Unshadowed, a method
search looks something like

cbm = ((base for base in type(inst).mro() if 'attr' in base.__dict__)
.next().__dict__['attr'].__get__(inst, type(inst)))

if this doesn't succeed and meet the __set__ vs shadowing logic, then you get
the instance attribute per se.

....but if I understand correctly, this suggests that if the runtime
can't find the attribute in the chain of classes and base classes, it
will look in the instance dictionary. The behavior of NZ above suggests that
it the runtime is _not_ doing that for __call__ as it would for a non-special name:
>>class NZ(object):
.... pass
....
>>nz = NZ()
nz.f = lambda : 42
nz.f()
42

My question is: did something about the way the special method names are
implemented change for new-style classes?

best, and thanks in advance,

Joe
Jul 8 '08 #1
5 1462
>
My question is: did something about the way the special method names are
implemented change for new-style classes?
>>class old:
pass
>>class new(object):
pass
>>testone = old()
testone.__call__ = lambda : 33
testone()
33
>>testtwo = new()
testtwo.__call__ = lambda : 33
testtwo()
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
testtwo()
TypeError: 'new' object is not callable
>>old.__call__
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
old.__call__
AttributeError: class old has no attribute '__call__'
>>new.__call__
<method-wrapper '__call__' of type object at 0x00CC40D8>
>>testone.__call__
<function <lambdaat 0x00C35EB0>
>>testtwo.__call__
<function <lambdaat 0x00C35B70>
>>dir(testtwo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'__weakref__']
>>dir(testone)
['__call__', '__doc__', '__module__']
>>dir(new)
['__class__', '__delattr__', '__dict__', '__doc__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'__weakref__']
>>dir(old)
['__doc__', '__module__']

I don't see __call__ in either class structures, but for new style
classes it is a wrapper and for old it is nothing. Not sure if that
helps, but this is rather over my head.
Jul 9 '08 #2
On Jul 8, 4:56*pm, Joseph Barillari <pyt...@barillari.orgwrote:
My question is: did something about the way the special method names are
implemented change for new-style classes?
Just off the top of my head, I'd guess that it's due to classes
already having a default __call__ method, used when you instatiate.
Remember, the Python compiler doesn't know the difference between
this:
a = MyClass
instance = a()
and this:
a = myFunc
result = a()
Jul 9 '08 #3


samwyse wrote:
On Jul 8, 4:56 pm, Joseph Barillari <pyt...@barillari.orgwrote:
>My question is: did something about the way the special method names are
implemented change for new-style classes?
I believe the difference is that for new-style classes, when special
methods are called 'behind the scenes' to implement built-in syntax and
methods, they are looked up directly on the class instead of first on
the instance. Note that functions attached to instances are *not*
methods and do not get combined with the instance as a bound method.

Jul 9 '08 #4
On Tue, 08 Jul 2008 17:56:45 -0400, Joseph Barillari wrote:
Hi python-list,

I've just started using new-style classes and am a bit confused as to
why I can't seem to alter methods with special names (__call__, etc.) of
new-style class instances.
[deploy weapon of mass snippage]

Here is a possible work-around:
>>class Special(object):
.... def __call__(self):
.... try:
.... return self.__dict__['__call__']()
.... except KeyError:
.... return 'foo'
....
>>s = Special()
s()
'foo'
>>s.__call__ = lambda: 'bar'
s()
'bar'

--
Steven
Jul 10 '08 #5
samwyse a écrit :
On Jul 8, 4:56 pm, Joseph Barillari <pyt...@barillari.orgwrote:
>My question is: did something about the way the special method names are
implemented change for new-style classes?

Just off the top of my head, I'd guess that it's due to classes
already having a default __call__ method,
>>object.__dict__.keys()
['__setattr__', '__reduce_ex__', '__new__', '__reduce__', '__str__',
'__getattribute__', '__class__', '__delattr__', '__repr__', '__hash__',
'__doc__', '__init__']

No __call__ method here.
used when you instatiate.
The __call__ method used to instanciate a class is actually the
metaclass __call__ method.
>>class MyType(type):
.... def __call__(self, *args, **kw):
.... print "pikaboo"
.... return type.__call__(self, *args, **kw)
....
>>class MyClass(object):
.... __metaclass__ = MyType
....
>>MyClass()
pikaboo
<__main__.MyClass object at 0x8334eec>
>>>

Jul 10 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
1917
by: Thomas Heller | last post by:
I once knew how to do it, but I cannot find or remember it anymore: How can I attach *class* methods to a type in C code, when I have a function PyObject *func(PyObject *type, PyObject *arg);...
99
5819
by: David MacQuigg | last post by:
I'm not getting any feedback on the most important benefit in my proposed "Ideas for Python 3" thread - the unification of methods and functions. Perhaps it was buried among too many other less...
51
6882
by: Noam Raphael | last post by:
Hello, I thought about a new Python feature. Please tell me what you think about it. Say you want to write a base class with some unimplemented methods, that subclasses must implement (or...
14
1856
by: Grant Edwards | last post by:
I want to subclass an IMAP connection so that most of the methods raise an exception if the returned status isn't 'OK'. This works, but there's got to be a way to do it that doesn't involve so...
125
7070
by: Raymond Hettinger | last post by:
I would like to get everyone's thoughts on two new dictionary methods: def count(self, value, qty=1): try: self += qty except KeyError: self = qty def appendlist(self, key, *values): try:
6
1805
by: Mayer | last post by:
Hello: Is there a way to see at the python prompt the names of all the public methods of a class or the names exported by a module? I know that GUI-based IDEs have a nifty way of displaying...
3
2946
by: User N | last post by:
Perhaps this is a stupid question, but here goes anyway. Given an instance of an arbitrary class, is it possible to change its base class at runtime? Here's my problem... I need to extend...
3
3187
by: =?Utf-8?B?VG9kZA==?= | last post by:
What is the memory footprint of static methods of a windows app running on a server when the server spins up multiple instances of the application? In my envirionment, we have a Citrix server...
5
1397
by: Gerardo Herzig | last post by:
Hi all. Im in this situation: I want to perform several kind of (validating) methods to a given value. Lets say i have a class named Number, and the following methods: is_really_a_number(),...
0
7234
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7344
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7412
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7069
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5652
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5060
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3216
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3203
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
775
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.