Classmethods are evil

Ivan Illarionov ivan.illarionov at gmail.com
Sat May 17 05:50:19 EDT 2008


On Sat, 17 May 2008 02:33:13 -0300, Gabriel Genellina wrote:

> En Sat, 17 May 2008 01:01:50 -0300, Ivan Illarionov
> <ivan.illarionov at gmail.com> escribió:
> 
>> After re-reading "Python is not Java" I finally came to conclusion that
>> classmethods in Python are a very Bad Thing.
>>
>> I can't see any use-case of them that couldn't be re-written more
>> clearly with methods of metaclass or plain functions.
> 
> A good use case for class methods are alternate constructors, like
> dict.from_keys. I don't think an alternate constructor would be more
> clear being a method of the metaclass - actually it belongs to the class
> itself, not to its metaclass.
> Metaclass methods are harder to find; they don't show in dir(instance)
> nor dir(class).
> Also the resolution order is harder to grasp for metaclasses - but this
> may be just lack of usage from my part...
> 
>> They have the following issues:
>> 1. You mix instance-level and class-level functionality in one place
>> making your code a mess.
> 
> Not necesarily; some classmethods are naturally tied to the class
> itself, not to the metaclass (like the constructor example above). But
> yes, *some* classmethods could be written as methods of their metaclass
> instead - but that doesn't always make sense.
> 
>> 2. They are slower than metaclass methods or plain functions.
> 
> Hu? How did you come to that?
> I've done a small test and a class method wins by a very minuscule but
> consistent advantage over a metaclass method:
> 
> class A(object):
>      color = "red"
> 
>      @classmethod
>      def foo(cls, x):
>          return getattr(cls, x)
> 
> class MetaB(type):
>      def foo(self, x):
>          return getattr(self, x)
> 
> class B(object):
>      __metaclass__ = MetaB
>      color = "red"
> 
> C:\TEMP>python -m timeit -s "from meta3 import A,B;a,b=A(),B()"
> "A.foo('color')"
> 1000000 loops, best of 3: 1.19 usec per loop
> 
> C:\TEMP>python -m timeit -s "from meta3 import A,B;a,b=A(),B()"
> "B.foo('color')"
> 1000000 loops, best of 3: 1.2 usec per loop

How did I come to this:
http://code.djangoproject.com/changeset/7098

I measured this and there was a marginal speed increase when classmethods 
wher moved to metaclass.

-- Ivan



More information about the Python-list mailing list