我有一些代码,我想交替传递实例或类。我在该代码中所做的就是调用一个我希望类和实例都有的方法(下面的例子中的方法go()
)。
不幸的是,我无法创建一个与常规方法同名的classmethod ...请参阅下面的示例。我最初预计第二次调用会生成a
而不是b
。
有关如何实现这一目标的任何建议吗?
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
答案 0 :(得分:4)
您可以使用特制的__get__()
方法创建自己的方法类型。
在这种方法中,您可以这样做:
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()
注意:以上内容未经过彻底测试,但似乎有效。然而,它应该被视为一种“解决方案 - 接近伪代码”,而不是解决方案。它应该让你知道如何实现你的目标。
答案 1 :(得分:3)
考虑重新使用formencode的classinstancemethod
装饰器。
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 ('<bound class method %s.%s>'
% (self.type.__name__, self.func.func_name))
else:
return ('<bound method %s.%s of %r>'
% (self.type.__name__, self.func.func_name, self.obj))
答案 2 :(得分:1)
如下:
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