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

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Nov 23 08:06:37 EST 2012


On Fri, 23 Nov 2012 09:52:25 +0100, Peter Otten wrote:

> Steven D'Aprano wrote:
>> http://code.activestate.com/recipes/577030/
> 
> Am I reading that right that you don't invoke method() as
> MyClass.method()? 

No. I give an example and explicitly state:

    You can use this class without instantiating:
    
    Example.method('else')  # returns 'something else'


> 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

That doesn't allow me to call A.method().

On the other hand, if method were a class method, then I could say 
A.method() or A(state).method, but in both cases I would get the default. 
So that isn't suitable.


[...]
> The same idea might work for the OP, too (but I'm not sure it's a good
> idea):
> 
> class B:

This needs to be a new-style class unless you're using Python 3.

>     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"

Without studying that in detail, it looks like that would be an 
alternative solution to the same problem. The downsides are:

- you have two distinct but almost identical implementations of 
  method "f", one called "f" and one called "inst_f";

- it works by shadowing method "f" in the instance, which may
  strike many people as too tricky for production software.


Me personally, I think the first objection is critical. Having to write 
the same method twice, with subtle differences, is inviting bugs.



-- 
Steven



More information about the Python-list mailing list