473,396 Members | 1,833 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Classmethods are evil

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.

They have the following issues:
1. You mix instance-level and class-level functionality in one place
making your code a mess.
2. They are slower than metaclass methods or plain functions.

I really want to hear your opinions on the subject.

-- Ivan
Jun 27 '08 #1
7 1715
On Sat, 17 May 2008 04:01:50 +0000, Ivan Illarionov wrote:
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.
*The* use case IMHO are alternative constructors. They belong to the
class, so functions are not as clear and it's possible to have more than
one class in a module with class methods of the same name, e.g.
`A.from_string()` and `B.from_string()` vs. `create_a_from_string()` and
`create_b_from_string()`.

And I don't see how functions can be inherited by sub classes like class
methods can.

Metaclasses are more clear than class methods? You must be joking!?
They have the following issues:
1. You mix instance-level and class-level functionality in one place
making your code a mess.
Writing meta classes just for alternative constructors seems to be more of
a mess to me. Too much magic for such a simple case for my taste.

Ciao,
Marc 'BlackJack' Rintsch
Jun 27 '08 #2
On May 17, 12:01 am, Ivan Illarionov <ivan.illario...@gmail.com>
wrote:
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.
I am probably one of the bigger advocates of metaclasses here, but
given a problem that could equally well be solved by the two I would
choose classmethods every time. Classmethods are more
straightforward, easier to follow (especially by people who aren't
used to working with metaclasses), and they hinder reusability less.

Classmethods have practical advantages. One thing you can do with a
classmethod that you can't directly do with a metaclass instancemethod
is to call it with an instance:

Python 2.5 (r25:51908, Apr 19 2007, 15:29:43)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more
information.
>>class A(type):
... def hello(self):
... print "hello"
...
>>class B(object):
... __metaclass__ = A
... @classmethod
... def world(self):
... print "world"
...
>>b = B()
b.world()
world
>>b.hello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'B' object has no attribute 'hello'

Though I can imagine some people would argue this is an advantage of
metaclasses.

They have the following issues:
1. You mix instance-level and class-level functionality in one place
making your code a mess.
2. They are slower than metaclass methods or plain functions.

I really want to hear your opinions on the subject.
I think neither of these reasons are very compelling. I don't even
agree with the premise of #1, but even granting that it's messy to do
that, I disagree that the mess would outweigh the drawbacks in
complexity and reusability that a metaclass would bring. As for #2, I
don't believe "class-level functionality" is often found in bottleneck
situations, so what does it matter what speed it is?
Carl Banks
Jun 27 '08 #3
Ivan Illarionov wrote:
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.
I agree with your sentiments, although I'm not sure I would pick metaclasses
over class methods... or over anything at all, for that matter. :-)
They have the following issues:
1. You mix instance-level and class-level functionality in one place
making your code a mess.
2. They are slower than metaclass methods or plain functions.
The way I see it, a class method is really just sugar for a function operating
on the class, living in the class namespace. As such, they are basically
redundant, and as you point out, they can always be replaced by a function
outside the class (and in fact, this was what people did before they came along
in 2.2). Personally, I don't use them... but some people like them. Different
strokes, and all that...

--Hans
Jun 27 '08 #4
Hans Nowak <ze*******************@gmail.comwrote:
The way I see it, a class method is really just sugar for a function
operating on the class, living in the class namespace. As such, they
are basically redundant, and as you point out, they can always be
replaced by a function outside the class (and in fact, this was what
people did before they came along in 2.2). Personally, I don't use
them... but some people like them. Different strokes, and all that...
In exactly the same way you could claim that a method is just sugar for a
function operating on the instance living in the instance namespace. As
such, you might think that they too are basically redundant, but they
aren't: with instance methods you get the ability to override the method in
a subclass without the caller needing to know whether they are calling the
original method or an overridden version.

With class methods you also get the ability to override the method in a
subclass, and again the caller doesn't need to know or care which variant
when they call it.

Say you have a class hierarchy with a from_keys() class method. If you want
to construct a new Foo you might call Foo.from_keys() without caring
whether the method is the original one defined in one of Foo's base classes
or a modified version specific to a Foo. If you were using functions then
you would need to define a new from_keys() function for every class in a
hierarchy, or at least for every different implementation in the hierarchy
and the caller would need to be careful to call the correct one. So we end
up with functions from_keys_Foo_or_Baz(cls) and from_keys_Bar() which is an
unmaintainable mess.

--
Duncan Booth http://kupuguy.blogspot.com
Jun 27 '08 #5
Ivan Illarionov a écrit :
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.
Plain functions don't give you polymorphic dispatch and can't be
overriden. Using metaclass methods requires a custom metaclass, which 1/
adds boilerplate code and cognitive load and 2/may bring problems,
specially wrt/ MI.
They have the following issues:
1. You mix instance-level and class-level functionality in one place
making your code a mess.
May I remind you that every name defined at the top-level of a class
statement becomes a class attribute ?

Anyway : most of the use case I've had so far for classmethods required
collaboration between the instance and the class, and I definitively
prefer to have related functionalities defined in one place.
2. They are slower than metaclass methods or plain functions.
Slower than plain functions, indeed - but so are instancemethods. Slower
that metaclass methods ? I never benchmarked this, but I don't see any
reason that should be the case. Anyway, you could also argue that
properties are slower than plain attributes, which are slower than local
vars etc...
I really want to hear your opinions on the subject.

Mine is that classmethods are a GoodThing that make simple thing easy.

Jun 27 '08 #6
On May 16, 9:01*pm, Ivan Illarionov <ivan.illario...@gmail.comwrote:
After re-reading "Python is not Java" I finally came to conclusion that
classmethods in Python are a very Bad Thing.
Sounds like a serious case of mis-learning.

Class methods are the preferred way to implement alternate
constructors. For good examples, see dict.fromkeys() or any of the
various datetime constructors.

Raymond
Jun 27 '08 #7
Ivan Illarionov a écrit :
On Mon, 19 May 2008 13:53:31 -0700, br*****************@gmail.com wrote:
>On 17 mai, 11:50, Ivan Illarionov <ivan.illario...@gmail.comwrote:
(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.

Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Paul Morrow | last post by:
Probably the best-loved features of Python are the shortcuts. The fact that you don't have to explicitly declare very much and that the language supports clear, shorthand syntax for frequently...
9
by: jfj | last post by:
Hi. Suppose this: ######################## def foo (x): print x f = classmethod (foo)
12
by: Andrew Jaffe | last post by:
Hi, I have a class with various class-level variables which are used to store global state information for all instances of a class. These are set by a classmethod as in the following (in...
2
by: Steven D'Aprano | last post by:
There's some subtle behaviour going on here that I don't really follow. Class methods apparently aren't classmethods. .... def method(self, *args): .... return self, args .......
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.