By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,050 Members | 1,009 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,050 IT Pros & Developers. It's quick & easy.

Overriding member methods in __init__

P: n/a
Given a condition at the time a class is instantiated, I want to change
how __call__ is used. From the example below, self.no is using self.yes
but self.__call__ is not. Can someone please explain why?

EXAMPLE:
class YesNo(object):
def __init__(self, which):
self.no = self.yes
self.__call__ = self.yes

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val

def __call__(self, val):
raise NotImplementedError()
>>y = YesNo(True)
y.yes('hello')
Yes hello
>>y.no('hello')
Yes hello
>>y('hello')
Traceback ....
Not ImplementedError

Dec 3 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
c james a écrit :
Given a condition at the time a class is instantiated, I want to change
how __call__ is used. From the example below, self.no is using self.yes
but self.__call__ is not. Can someone please explain why?
IIRC, you can't override __magic__ methods on a per-instance basis.
EXAMPLE:
class YesNo(object):
def __init__(self, which):
self.no = self.yes
self.__call__ = self.yes

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val

def __call__(self, val):
raise NotImplementedError()

This should do the trick:

class YesNo(object):
def __init__(self, which):
self.which = which

def __call__(self, val):
return (self.no, self.yes)[self.which](val)

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val
Dec 3 '07 #2

P: n/a
Bruno Desthuilliers wrote:
c james a écrit :
>Given a condition at the time a class is instantiated, I want to change
how __call__ is used. From the example below, self.no is using self.yes
but self.__call__ is not. Can someone please explain why?

IIRC, you can't override __magic__ methods on a per-instance basis.
This should do the trick:

class YesNo(object):
def __init__(self, which):
self.which = which

def __call__(self, val):
return (self.no, self.yes)[self.which](val)

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val
Thanks, I was trying to eliminate another level of indirection with a
test at each invocation of __call__

Dec 3 '07 #3

P: n/a
c james <cj****@callone.netwrote:

Thanks, I was trying to eliminate another level of indirection with a
test at each invocation of __call__

Try using different subclasses for each variant:

class YesNo(object):
def __new__(cls, which, *args, **kw):
if cls is YesNo:
if which:
return object.__new__(Yes)
else:
return object.__new__(No)

def __init__(self, which, *args, **kw):
print "New", self.__class__, which, args, kw

def __call__(self, val):
raise NotImplementedError()
class Yes(YesNo):
def __call__(self, val):
print 'Yes', val
class No(YesNo):
def __call__(self, val):
print 'No', val

>>y = YesNo(True)
New <class '__main__.Yes'True () {}
>>y('hello')
Yes hello
>>n = YesNo(False)
New <class '__main__.No'False () {}
>>n('hello')
No hello
>>>
Dec 3 '07 #4

P: n/a
c james <cj****@callone.netwrites:
>class YesNo(object):
def __init__(self, which):
self.which = which

def __call__(self, val):
return (self.no, self.yes)[self.which](val)

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val

Thanks, I was trying to eliminate another level of indirection with a
test at each invocation of __call__
Allowing instance lookup of __call__ would slow down normal uses of
the internal __call__ mechanism. Since it used for all function and
method calls, it needs to remain extremely fast. If you're really
worried about performance, you can define YesNo.__new__ to return
either a Yes instance or a No instance, depending on the value:

class YesNo(object):
def __new__(cls, which):
if which:
return object.__new__(Yes)
else:
return object.__new__(No)

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val

class Yes(YesNo):
def __call__(self, val):
self.yes(val) # no check at every call

class No(YesNo):
def __call__(self, val):
self.no(val) # likewise
>>x = YesNo(True)
x
<__main__.Yes object at 0xb7d0ee8c>
>>x('foo')
Yes foo
>>y = YesNo(False)
y
<__main__.No object at 0xb7d0eeec>
>>y('foo')
No foo
>>isinstance(x, YesNo)
True
>>isinstance(y, YesNo)
True
Dec 3 '07 #5

P: n/a
On Dec 3, 3:36 pm, Hrvoje Niksic <hnik...@xemacs.orgwrote:
Allowing instance lookup of __call__ would slow down normal uses of
the internal __call__ mechanism. Since it used for all function and
method calls, it needs to remain extremely fast. If you're really
worried about performance, you can define YesNo.__new__ to return
either a Yes instance or a No instance, depending on the value:

class YesNo(object):
def __new__(cls, which):
if which:
return object.__new__(Yes)
else:
return object.__new__(No)

def yes(self, val):
print 'Yes', val

def no(self, val):
print 'No', val

class Yes(YesNo):
def __call__(self, val):
self.yes(val) # no check at every call

class No(YesNo):
def __call__(self, val):
self.no(val) # likewise
Why not simply do:

class YesNo(object):
def __init__(self, which):
self.yesno = which and self.yes or self.no
def yes(self, val):
print 'Yes', val
def no(self, val):
print 'No', val
def __call__(self, val):
self.yesno(val)

I don't know which is fastest but I don't think there would be much
difference.

--
Arnaud

Dec 3 '07 #6

P: n/a
Arnaud Delobelle wrote:
Why not simply do:

class YesNo(object):
def __init__(self, which):
self.yesno = which and self.yes or self.no
def yes(self, val):
print 'Yes', val
def no(self, val):
print 'No', val
def __call__(self, val):
self.yesno(val)

I don't know which is fastest but I don't think there would be much
difference.

--
Arnaud
This is more in the spirit of what I was trying to accomplish.
Originally, I was unaware the __call__ could not be assigned a different
method.

Dec 3 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.