开发者

Static and instance methods in Python [duplicate]

This question already has answers here: Can a method be used as either a staticmethod or instance method? (4 answers) Closed 9 years ago.

Can I define a Python method to be both static and instance at the same time? Something like:

class C(object):
    @staticmethod
    def a(self, arg1):
        if self:
            blah
        blah

So that I can call it with both:

C.a(arg1)
C().a(arg1)

The intent is to be able to run two sets of logics开发者_开发百科. If accessed as an instance method, it would make use of instance variables and do stuff. If access as a static method, it will do without.


import functools

class static_or_instance(object):
  def __init__(self, func):
    self.func = func

  def __get__(self, instance, owner):
    return functools.partial(self.func, instance)

class C(object):
  @static_or_instance
  def a(self, arg):
    if self is None:
      print "called without self:", arg
    else:
      print "called with self:", arg

C.a(42)
C().a(3)


formencode has a classinstancemethod decorator, which does what what you want. It requires the method to have 2 arguments (self and cls, one of them could get passed None depending on calling context)

Lifted from 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 not kw.has_key('self') and not kw.has_key('cls'), (
            "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))

Sample usage

class A(object):
    data = 5

    @classinstancemethod
    def print_(self=None, cls=None):
        ctx = self or cls
        print ctx.data


>>> A.print_()
5
>>> a = A()
>>> a.data = 4
>>> a.print_()
4


No. What would self mean inside the method, if you could do that?


Your code will work if you remove the self parameter to a(). When you call it with C().a(arg1) the instance is ignored.

But you want this method to work as both a static method and a method that receives an instance. You can't have it both ways.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜