Static and instance methods in Python [duplicate]

岁酱吖の 提交于 2019-12-10 12:40:27

问题


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.


回答1:


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)



回答2:


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



回答3:


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




回答4:


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.



来源:https://stackoverflow.com/questions/5892619/static-and-instance-methods-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!