The same method for class and instance
I have class Books
and method 开发者_开发知识库select
in it. Also there is an instance of that class called book
. I want to be able to do both Books.select(where='...')
and book.select(where='...')
:
class Books():
def select(obj, where):
print(obj, where)
book = Books()
Books.select(where='asdf')
book.select(where='asdf')
The above obviously doesn't work, because select
is an instance bound method:
Traceback (most recent call last):
File "test.py", line 7, in <module>
Books.select(where='asdf')
TypeError: select() takes exactly 2 arguments (1 given)
A working code:
class Books():
@staticmethod
def select(obj, where):
print(obj, where)
book = Books()
Books.select(Books, where='asdf')
Books.select(book, where='asdf')
And i get:
vic@wic:~/projects/snippets$ python3 test.py
<class '__main__.Books'> asdf
<__main__.Books object at 0x17fd6d0> asdf
But i have to manually pass the class or its instance as the first argument to the select
method - not what i want.
If i make select
a class method:
class Books():
@classmethod
def select(obj, where):
print(obj, where)
book = Books()
Books.select(where='asdf')
book.select(where='asdf')
I always get a class as the first argument:
vic@wic:~/projects/snippets$ python3 test.py
<class '__main__.Books'> asdf
<class '__main__.Books'> asdf
But i want to get an instance in the second case.
So, is there a way to accomplish what i want without manually passing the class/instance as the first argument to a static method?
You could use a 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')
yields
<class '__main__.Books'> asdf
<__main__.Books object at 0xb7696dec> asdf
Solution using a descriptor and a decorator:
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')
Result:
<class '__main__.Books'> asdf
<__main__.Books object at 0x2695890> asdf
Just an example I founded on http://code.activestate.com/recipes/52304-static-methods-aka-class-methods-in-python/
You create a little wrapper:
class Callable:
def __init__(self, anycallable):
self.__call__ = anycallable
And then defines your class and a class variable inside it.
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
精彩评论