Classmethods are evil

Ivan Illarionov ivan.illarionov at gmail.com
Tue May 20 05:18:32 EDT 2008


On Mon, 19 May 2008 13:53:31 -0700, bruno.desthuilliers at gmail.com wrote:

> On 17 mai, 11:50, Ivan Illarionov <ivan.illario... at gmail.com> wrote:
>> On Sat, 17 May 2008 02:33:13 -0300, Gabriel Genellina wrote:
>> > En Sat, 17 May 2008 01:01:50 -0300, Ivan Illarionov
>> > <ivan.illario... 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.
> 
> IIRC (please correct me if I'm wrong), this part of code is only called
> when the class is created - in which case it makes sense to move it
> where it belongs, ie to the metaclass. This is by no mean a use case for
> classmethods.

Yes, this is not the use case for class methods, but they where used 
there. The whole point of my post was to say that classmethods are used 
in a wrong way too often and most of Python programmers don't know that 
the same thing can be implemented with metaclass methods.

-- Ivan



More information about the Python-list mailing list