Take the 2-minute tour ×

I have some code which I would like to pass instances or classes interchangeably. All I will do in that code is to call a method that I expect both classes and instances to have (the method go() in the example below).

Unfortunately, I can't create a classmethod with the same name of a regular method... See example below. I initially expected the second call to produce an a instead of a b.

Any advice on how to achieve this?

>>> class A(object):
...     def go(self):
...             print "a"
...     @classmethod
...     def go(cls):
...             print "b"
>>> a=A()
>>> a.go()
>>> A.go()
share|improve this question
What are you actually trying to achieve? Why can't you put all of your code in a classmethod? Or, if not, have two separate classes? Or always pass instances with default values? –  Marcin May 2 '12 at 12:14
you can't assign 2 different methods/propierties to the same name, is like trying to stick 2 numbers into an integer variable. –  KurzedMetal May 2 '12 at 12:16
This isn't duck typing. Duck typing is expecting two separate classes - which don't necessarily share an ancestor - to have the same methods. –  Daniel Roseman May 2 '12 at 12:19
@DanielRoseman Exactly! a has the class A. And A has the class type... They are separate classes, which don't necessarily share the same ancestor :) –  Filipe Correia May 2 '12 at 12:27

3 Answers 3

up vote 3 down vote accepted

Consider reusing the classinstancemethod decorator from formencode.


class classinstancemethod(object):
    Acts like a class method when called from a class, like an
    instance method when called by an instance.  The method should
    take two arguments, 'self' and 'cls'; one of these will be None
    depending on how the method was called.

    def __init__(self, func):
        self.func = func

    def __get__(self, obj, type=None):
        return _methodwrapper(self.func, obj=obj, type=type)

class _methodwrapper(object):

    def __init__(self, func, obj, type):
        self.func = func
        self.obj = obj
        self.type = type

        assert 'self' not in kw and 'cls' not in kw, (
            "You cannot use 'self' or 'cls' arguments to a "
        return self.func(*((self.obj, self.type) + args), **kw)

    def __repr__(self):
        if self.obj is None:
            return ('<bound class method %s.%s>'
                    % (self.type.__name__, self.func.func_name))
            return ('<bound method %s.%s of %r>'
                    % (self.type.__name__, self.func.func_name, self.obj))
share|improve this answer
self will be None if called via class. But I'm not sure cls will be None fi called via instance - I think this is only valid for Py3. In Py2, the class will be given even in the instance case. –  glglgl May 2 '12 at 12:34
Did so. Output were the lines i: <__main__.A object at 0xb74976ac> <class '__main__.A'> and c: None <class '__main__.A'>. –  glglgl May 2 '12 at 12:37
Whatever, maybe you just submit a patch to formencode to fix the comment. Anyway, it does what you asked. –  ddaa May 2 '12 at 12:37
Just tested under Py3 - it gives the cls as well in both cases. Nevertheless, it was not me who asked :-) –  glglgl May 2 '12 at 12:39
@ddaa I've noticed you edited the question title to make clearer. I still think it makes sense to have "duck typing" in there somewhere though, because that's how I first thought about it, and I'm sure others might think about it that way too. In python, both classes and instances are... instances. So it makes sense for me to think of this as duck typing. Do you agree? –  Filipe Correia May 2 '12 at 14:11

You could create an own method type with a specially crafted __get__() method.

In this method, you could do something like this:

class combimethod(object):
    def __init__(self, func):
        self._func = func
    def classmethod(self, func):
        self._classfunc = classmethod(func)
        return self
    def __get__(self, instance, owner):
        if instance is None:
            return self._classfunc.__get__(instance, owner)
            return self._func.__get__(instance, owner)

class A(object):
    def go(self):
        print "instance", self
    def go(cls):
        print "class", cls

print "i:",
print "c:",

NOTE: The above is not very thoroughly tested, but seems to work. Nevertheless, it should be seen as a kind of "solution-near pseudo-code", not as a solution. It should give you an idea how to achieve your goal.

share|improve this answer

How about something like:

import inspect

class A(object):
   def go(obj):
      if inspect.isclass(obj):
         print 'class'
         print 'instance'

A.go(int) # class
A.go(1)   # instance
A.go(A)   # class
A.go(A()) # instance
share|improve this answer
Thanks. This is pretty close, but I have to pass the class itself as an argument, which is not exactly what I was looking for. –  Filipe Correia May 2 '12 at 14:02

Your Answer


