Classmethods are evil

bruno.desthuilliers at gmail.com bruno.desthuilliers at gmail.com
Mon May 19 16:53:31 EDT 2008


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.





More information about the Python-list mailing list