method that can be called from a class and also from an instance

Peter Otten __peter__ at web.de
Fri Nov 23 03:52:25 EST 2012


Steven D'Aprano wrote:
> On 2012年11月22日 16:51:27 +0100, Peter Otten wrote:
>>> Marc Aymerich wrote:
>>>>> Hi,
>>>>>> I want to create a method within a class that is able to accept either
>>> a class or an instance.
> [...]
>> Why would you overload a method that way?
>>> The use-case I have is that I have a number of classes with default
> state. Most instances don't override any of the state, so the instances
> don't add anything except an extra conceptual layer:
>> instance = MyClass() # notice that there are no arguments passed
> instance.method(args)
>> Since the instances don't have any state except for that already held by
> the class, they are redundant and pointless. Just knowing the class is
> enough to specify the behaviour. If I used class methods, I could do this:
>> MyClass.method(args)
>>> But here's the thing -- sometimes I *do* have instances that override the
> default state:
>> instance = MyClass(x, y, z)
> instance.method(args)
>> Now if method is a class method, my per-instance state is ignored. So I
> want a method that can be called from the class, and see the default
> state, or from the instance, and see the per-instance state. Neither
> classmethod, staticmethod nor ordinary instance methods do the job, but
> my custom dualmethod does.
>> http://code.activestate.com/recipes/577030/

Am I reading that right that you don't invoke method() as MyClass.method()? 
Then I'd probably use class attributes to store the default state and shade 
them by instance attributes as needed.
class A:
 state = "default"
 def __init__(self, state=None):
 if state is not None:
 self.state = state
 def method(self): return self.state
assert A().method() == "default"
assert A("special").method() == "special"
The same idea might work for the OP, too (but I'm not sure it's a good 
idea):
class B:
 def inst_f(self):
 return "instance"
 @classmethod
 def f(class_):
 return "class"
 def __init__(self):
 self.f = self.inst_f
assert B.f() == "class"
assert B().f() == "instance"


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /