Métodos de escritura y clase de pato (o, ¿cómo usar un método de una clase y una instancia?)

Tengo un código que me gustaría pasar instancias o clases de manera intercambiable. Todo lo que haré en ese código es llamar a un método que espero que tengan tanto las clases como las instancias (el método go() en el siguiente ejemplo).

Desafortunadamente, no puedo crear un método de clase con el mismo nombre de un método regular … Vea el ejemplo a continuación. Inicialmente esperaba que la segunda llamada produjera una a lugar de una b .

¿Algún consejo sobre cómo lograr esto?

 Type "help", "copyright", "credits" or "license" for more information. >>> class A(object): ... def go(self): ... print "a" ... @classmethod ... def go(cls): ... print "b" ... >>> a=A() >>> a.go() b >>> A.go() b 

Considere reutilizar el decorador classinstancemethod de formencode.

https://bitbucket.org/formencode/official-formencode/src/06d52c5b33c9/formencode/declarative.py

 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 def __call__(self, *args, **kw): assert 'self' not in kw and 'cls' not in kw, ( "You cannot use 'self' or 'cls' arguments to a " "classinstancemethod") return self.func(*((self.obj, self.type) + args), **kw) def __repr__(self): if self.obj is None: return ('' % (self.type.__name__, self.func.func_name)) else: return ('' % (self.type.__name__, self.func.func_name, self.obj)) 

Podría crear un tipo de método propio con un método __get__() especialmente diseñado.

En este método, podrías hacer algo como esto:

 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) else: return self._func.__get__(instance, owner) class A(object): @combimethod def go(self): print "instance", self @go.classmethod def go(cls): print "class", cls a=A() print "i:", a.go() print "c:", A.go() 

NOTA: Lo anterior no está muy probado, pero parece funcionar. Sin embargo, debería verse como una especie de “pseudo-código cercano a la solución”, no como una solución. Debería darte una idea de cómo lograr tu objective.

¿Qué tal algo como:

 import inspect class A(object): @staticmethod def go(obj): if inspect.isclass(obj): print 'class' else: print 'instance' A.go(int) # class A.go(1) # instance A.go(A) # class A.go(A()) # instance