2

インスタンスまたはクラスを交換可能に渡したいコードがいくつかあります。そのコードで行うことは、クラスとインスタンスの両方にあると思われるメソッド (go()以下の例のメソッド) を呼び出すことだけです。

残念ながら、通常のメソッドと同じ名前のクラスメソッドを作成することはできません...以下の例を参照してください。最初は、2 番目の呼び出しでaではなく が生成されると予想していましたb

これを達成する方法について何かアドバイスはありますか?

Type "help", "copyright", "credits" or "license" for more information.
>>> class A(object):
...     def go(self):
...             print "a"
...     @classmethod
...     def go(cls):
...             print "b"
... 
>>> a=A()
>>> a.go()
b
>>> A.go()
b
4

3 に答える 3

4

特別に細工されたメソッドを使用して、独自のメソッド タイプを作成できます__get__()

この方法では、次のようなことができます。

class combimethod(object):
    def __init__(self, func):
        self._func = func
    def classmethod(self, func):
        self._classfunc = classmethod(func)
        return self
    def __get__(self, instance, owner):
        if instance is None:
            return self._classfunc.__get__(instance, owner)
        else:
            return self._func.__get__(instance, owner)

class A(object):
    @combimethod
    def go(self):
        print "instance", self
    @go.classmethod
    def go(cls):
        print "class", cls

a=A()
print "i:",
a.go()
print "c:",
A.go()

注: 上記は十分にテストされていませんが、動作するようです。それにもかかわらず、これはソリューションとしてではなく、一種の「ソリューションに近い疑似コード」と見なされるべきです。目標を達成するためのアイデアを提供する必要があります。

于 2012-05-02T12:18:59.277 に答える
3

classinstancemethodformencodeのデコレーターを再利用することを検討してください。

https://bitbucket.org/formencode/official-formencode/src/06d52c5b33c9/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 'self' not in kw and 'cls' not in kw, (
            "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))
于 2012-05-02T12:29:09.957 に答える
1

次のようなものはどうですか:

import inspect

class A(object):
   @staticmethod
   def go(obj):
      if inspect.isclass(obj):
         print 'class'
      else:
         print 'instance'

A.go(int) # class
A.go(1)   # instance
A.go(A)   # class
A.go(A()) # instance
于 2012-05-02T12:14:15.753 に答える