2016-07-28 5 views
1

Python3では、インスタンスメソッドは、obj.ix()またはFoo.ix(obj)という2つの方法で呼び出すことができます。それがよいアイデアかどうかを脇に置く:後者を使うとき、インスタンスメソッドがアクセスされたクラスを取得する方法はありますか?アンバインドメソッドを呼び出し、アクセスされたクラスを取得しますか?

class Foo(object): 
    @classmethod 
    def cx(cls, obj): 
     print(cls.X) 
    def ix(self): 
     # Any way to get the class that ix was accessed through? 
     print(self.X) 

class AFoo(Foo): 
    X = "A" 

class BFoo(Foo): 
    X = "B" 


a = AFoo() 
AFoo.cx(a) # Prints "A" 
AFoo.ix(a) # Prints "A" 

b = BFoo() 
BFoo.cx(b) # Prints "B" 
BFoo.ix(b) # Prints "B" 

AFoo.cx(b) # Prints "A" 
AFoo.ix(b) # Prints "B" -> I would like "A", like classmethod. 

BFoo.cx(a) # Prints "B" 
BFoo.ix(a) # Prints "A" -> I would like "B", like classmethod. 

あなたが見ることができるように、目的の動作は、クラスメソッドで実現するのは簡単ですが、インスタンスメソッドと同じことを行う方法があるように表示されません。

答えて

2

いいえ。この情報は保持されません。その情報が必要な場合は、新しいメソッドタイプを実装するカスタム記述子を作成する必要があります。たとえば:

import functools 

class CrazyMethod: 
    def __init__(self, func): 
     self.func = func 
    def __get__(self, instance, owner): 
     if instance is None: 
      return functools.partial(self.func, owner) 
     return functools.partial(self.func, instance, instance) 

class Foo: 
    @CrazyMethod 
    def foo(accessed_through, self): 
     print(accessed_through) 

class Bar(Foo): pass 

obj = Bar() 
obj.foo()  # <__main__.Bar object at 0xb727dd4c> 
Bar.foo(obj) # <class '__main__.Bar'> 
Foo.foo(obj) # <class '__main__.Foo'> 
+0

非常に興味深いを!それについては、複数の方法があるようですが、これは正当な答えですので、私はそれを受け入れました。 – kloffy

1

私はすでにuser2357112の答えを受け入れたが、念のために誰もが興味を持っている私は(A class method which behaves differently when called as an instance method?に基づいて)それを行うための別の方法が見つかりました:、おかげ

import types 

class Foo(object): 
    @classmethod 
    def x(cls, obj): 
     print(cls.X) 
    def __init__(self): 
     self.x = types.MethodType(type(self).x, self) 

class AFoo(Foo): 
    X = "A" 

class BFoo(Foo): 
    X = "B" 

a = AFoo() 
b = BFoo() 

a.x()  # Prints "A" 
AFoo.x(a) # Prints "A" 
AFoo.x(b) # Prints "A" 

b.x()  # Prints "B" 
BFoo.x(b) # Prints "B" 
BFoo.x(a) # Prints "B" 
関連する問題