web-dev-qa-db-ja.com

Pythonで別のクラスの関数内の呼び出し元クラス名を取得するにはどうすればよいですか?

私の目的は、このためにアプリケーションのシーケンス図を刺激することです。実行時に呼び出し元と呼び出し先のクラス名に関する情報が必要です。呼び出し元の関数を正常に取得できますが、呼び出し元のクラス名を取得できませんか?

#Scenario caller.py:

import inspect

class A:

    def Apple(self):
        print "Hello"
        b=B()
        b.Bad()



class B:

    def Bad(self):
        print"dude"
        print inspect.stack()


a=A()
a.Apple()

スタックを印刷したとき、呼び出し元クラスに関する情報はありませんでした。それで、実行時に呼び出し元クラスを取得することは可能ですか?

26
Kaushik

まあ、プロンプトを少し掘り下げた後、ここに私が得るものがあります:

stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__
the_method = stack[1][0].f_code.co_name

print("I was called by {}.{}()".format(str(calling_class), calling_code_name))
# => I was called by A.a()

呼び出されたとき:

➤ python test.py
A.a()
B.b()
  I was called by __main__.A.a()

ファイルtest.py

import inspect

class A:
  def a(self):
    print("A.a()")
    B().b()

class B:
  def b(self):
    print("B.b()")
    stack = inspect.stack()
    the_class = stack[1][0].f_locals["self"].__class__
    the_method = stack[1][0].f_code.co_name
    print("  I was called by {}.{}()".format(str(the_class), the_method))

A().a()

オブジェクト以外から呼び出されたときの動作がわからない。

32
brice

Pythonからの回答を使用する:「フレーム」オブジェクトからクラス情報を取得する方法

私はこのようなものを手に入れます...

import inspect

def get_class_from_frame(fr):
  args, _, _, value_dict = inspect.getargvalues(fr)
  # we check the first parameter for the frame function is
  # named 'self'
  if len(args) and args[0] == 'self':
    # in that case, 'self' will be referenced in value_dict
    instance = value_dict.get('self', None)
    if instance:
      # return its class
      return getattr(instance, '__class__', None)
  # return None otherwise
  return None


class A(object):

    def Apple(self):
        print "Hello"
        b=B()
        b.Bad()

class B(object):

    def Bad(self):
        print"dude"
        frame = inspect.stack()[1][0]
        print get_class_from_frame(frame)


a=A()
a.Apple()

これは私に次の出力を与えます:

Hello
dude
<class '__main__.A'>

明らかに、これはクラス自体への参照を返します。クラスの名前が必要な場合は、__name__属性から取得できます。

残念ながら、これはクラスまたは静的メソッドでは機能しません...

4
mgilson

おそらくこれはいくつかのPythonプログラミングプロトコルを壊していますが、Badがalwaysで呼び出し元のクラスをチェックする場合は、呼び出し元の__class__呼び出しの一部としてそれに対して?

class A:

    def Apple(self):
        print "Hello"
        b=B()
        b.Bad(self.__class__)



class B:

    def Bad(self, cls):
        print "dude"
        print "Calling class:", cls


a=A()
a.Apple()

結果:

Hello
dude
Calling class: __main__.A

これが不適切な形式であり、inspectを使用することが呼び出し元のクラスを取得するための好ましい方法である場合は、その理由を説明してください。私はまだより深いPython概念について学習しています。

3

Inspect.stack()の戻り値にインデックスを付ける代わりに、メソッドinspect.currentframe()を使用して、インデックス付けを回避できます。

prev_frame = inspect.currentframe().f_back
the_class = prev_frame.f_locals["self"].__class__
the_method = prev_frame.f_code.co_name
0
djeongo

スタックからクラス変数にクラスインスタンス名を格納するには:

import inspect

class myClass():

    caller = ""

    def __init__(self):
        s = str(inspect.stack()[1][4]).split()[0][2:]
        self.caller = s

    def getInstanceName(self):
        return self.caller

この

myClassInstance1 = myClass()
print(myClassInstance1.getInstanceName())

印刷されます:

myClassInstance1
0
Mika72