2

とにかくこのようなことをすることはありますか?

class A:
    def foo(self):
        if isinstance(caller, B):
           print "B can't call methods in A"
        else:
           print "Foobar"
class B:
    def foo(self, ref): ref.foo()

class C:
    def foo(self, ref): ref.foo()


a = A();
B().foo(a)    # Outputs "B can't call methods in A"
C().foo(a)    # Outputs "Foobar"

呼び出し元は、呼び出し元Aメソッドのオブジェクトのクラスを決定するために、何らかの形式のイントロスペクションを使用しますか?

編集

最後に、いくつかの提案に基づいてこれをまとめました。

import inspect
...
def check_caller(self, klass):
    frame = inspect.currentframe()
    current = lambda : frame.f_locals.get('self')
    while not current() is None:
        if isinstance(current(), klass): return True
        frame = frame.f_back
    return False

提供されたすべての理由で完璧ではありませんが、回答に感謝します。彼らは大きな助けになりました。

4

3 に答える 3

6

呼び出し元がメソッドであると仮定すると、前のフレームを見てself、ローカルから選択することで可能です。

class Reciever:
    def themethod(self):
        frame = sys._getframe(1)
        arguments = frame.f_code.co_argcount
        if arguments == 0:
            print "Not called from a method"
            return
        caller_calls_self = frame.f_code.co_varnames[0]
        thecaller = frame.f_locals[caller_calls_self]
        print "Called from a", thecaller.__class__.__name__, "instance"

なんてこった、でもうまくいく。なぜこれをやりたいのかはまったく別の問題ですが、もっと良い方法があると思います。A is not allowed to call B という概念全体が間違いである可能性があります。

于 2009-09-30T12:20:31.713 に答える
4

呼び出し元は常に A のインスタンスです。B メソッド内で呼び出すという事実は、それを変更しません。B.fooつまり、Insioderefは のインスタンスでAあるため、呼び出しref.foo()は の呼び出しでAあり、その呼び出しにBは関与しません (トップレベルで発生する可能性があります)。

唯一の健全な方法は、参照を渡して、selfA が B かどうかを確認できるようにすることです。

class A(object):
    def foo(self, caller=None):
        if isinstance(caller, B):
           print "B can't call methods in A"
        else:
           print "Foobar"

class B(object):
    def foo(self, ref): ref.foo(self)

class C(object):
    def foo(self, ref): ref.foo(self)

a = A();
B().foo(a)    # Outputs "B can't call methods in A"
C().foo(a)    # Outputs "Foobar"
a.foo()       # Outputs "Foobar"
于 2009-09-30T12:02:03.280 に答える
0

このようなものは、あなたのニーズをよりよく満たすかもしれません:

class A(object):
    def foo(self):
        # do stuff

class B(A):
    def foo(self):
        raise NotImplementedError

class C(A):
    pass

...しかし、あなたが何をしようとしているのかを正確に知らずに言うのは難しい.

于 2009-09-30T13:58:58.887 に答える