Classmethods are evil
Bruno Desthuilliers
bruno.42.desthuilliers at websiteburo.invalid
Tue May 20 06:16:59 EDT 2008
Ivan Illarionov a écrit :
> 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:
>(snip)
>>> 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.
Don't blame the tool for being misused.
> The whole point of my post was to say that classmethods are used
> in a wrong way too often
I think it's the first time I see such a misuse of classmethods, and I
have read quite a lot of (sometimes pretty hairy) Python code.
> and most of Python programmers don't know that
> the same thing can be implemented with metaclass methods.
I'd say that most Python programmers using metaclasses know when to use
a metaclass method and when to use a classmethod. One case of (slight)
misuse is certainly not enough to infer a general rule, and that doesn't
make classmethods bad in anyway. And while we're at it, I'd consider
using a custom metaclass only to implement the equivalent of a
classmethod a misuse too - and in this case, kind of a WTF.
As a last point, there's at least one very big difference between a
metaclass method and a classmethod, which is that you cannot call a
metaclass method on an instance:
class MyMeta(type):
def bar(cls):
print "%s.bar()" % cls
class Foo(object):
__metaclass__ = MyMeta
@classmethod
def baaz(cls):
print "%s.baaz()" % cls
Foo.baaz()
Foo.bar()
f = Foo()
f.baaz()
f.bar()
=>
<class '__main__.Foo'>.baaz()
<class '__main__.Foo'>.bar()
<class '__main__.Foo'>.baaz()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/tmp/python-18506gCT.py", line 17, in <module>
f.bar()
AttributeError: 'Foo' object has no attribute 'bar'
I've had use case where I needed to call classmethods on instances,
using a metaclass method would have required an explicit call, ie
type(obj).some_method() instead of obj.some_method(), which would have
uselessly exposed this knowledge to client code.
More information about the Python-list
mailing list