我有课程Books
和方法select
。此外,还有一个名为book
的类的实例。我希望能够同时执行Books.select(where='...')
和book.select(where='...')
:
class Books():
def select(obj, where):
print(obj, where)
book = Books()
Books.select(where='asdf')
book.select(where='asdf')
上面显然不起作用,因为select
是一个实例绑定方法:
Traceback (most recent call last):
File "test.py", line 7, in <module>
Books.select(where='asdf')
TypeError: select() takes exactly 2 arguments (1 given)
工作代码:
class Books():
@staticmethod
def select(obj, where):
print(obj, where)
book = Books()
Books.select(Books, where='asdf')
Books.select(book, where='asdf')
我得到了:
vic@wic:~/projects/snippets$ python3 test.py
<class '__main__.Books'> asdf
<__main__.Books object at 0x17fd6d0> asdf
但我必须手动将类或其实例作为select
方法的第一个参数传递 - 而不是我想要的。
如果我使用select
类方法:
class Books():
@classmethod
def select(obj, where):
print(obj, where)
book = Books()
Books.select(where='asdf')
book.select(where='asdf')
我总是把一个班作为第一个论点:
vic@wic:~/projects/snippets$ python3 test.py
<class '__main__.Books'> asdf
<class '__main__.Books'> asdf
但我想在第二种情况下得到一个实例。
那么,有没有办法在没有手动将类/实例作为第一个参数传递给静态方法的情况下实现我想要的东西?
答案 0 :(得分:2)
您可以使用descriptor:
class Select(object):
def __get__(self,obj,objtype):
x=objtype if obj is None else obj
def select(where):
print(x,where)
return select
class Books(object):
select=Select()
book = Books()
Books.select(where='asdf')
book.select(where='asdf')
产量
<class '__main__.Books'> asdf
<__main__.Books object at 0xb7696dec> asdf
答案 1 :(得分:2)
解决方案:
class class_or_instance_method():
def __init__(self, method):
self.method = method
def __get__(self, obj, objtype):
x = obj or objtype
def wrapped(*args, **kwargs):
return self.method(x, *args, **kwargs)
return wrapped
class Books():
@class_or_instance_method
def select(obj, where):
print(obj, where)
book = Books()
Books.select(where='asdf')
book.select(where='asdf')
结果:
<class '__main__.Books'> asdf
<__main__.Books object at 0x2695890> asdf
答案 2 :(得分:0)
我在http://code.activestate.com/recipes/52304-static-methods-aka-class-methods-in-python/
创立的一个例子你创建了一个小包装器:
class Callable:
def __init__(self, anycallable):
self.__call__ = anycallable
然后在其中定义您的类和类变量。
class Class2:
def static2(name):
print "Hi there",name
static2 = Callable(static2)
# now, a call such as:
Class2.static2("Peter")
# works just fine, and as-expected