类和实例的方法相同

时间:2011-10-13 07:39:43

标签: python python-3.x

我有课程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

但我想在第二种情况下得到一个实例。

那么,有没有办法在没有手动将类/实例作为第一个参数传递给静态方法的情况下实现我想要的东西?

3 个答案:

答案 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