2017-04-19 1 views
5

関数内で関数が呼び出されているか、=で変数に代入されているかどうかを知る方法はありますか?関数は、関数の呼び出し方法を知ることができますか?

私はこのような何かやりたい:これらの出力を与えるだろう

def func(): 
    if 'assigned with equal': 
     return 5 
    else: 
     print 'not assigned' 

を:

func() 
-> 'not assigned' 
a = func() 
a 
-> 5 
+10

それはできません。 –

+1

私はこれをやろうとしません。返すバージョンが1つあり、必要に応じてコールサイトで戻り値を出力します。一般的に、関数は一貫して同じ型を返すようにするか、少なくとも一貫して使用可能な値を返すようにしてください。 – Carcigenicate

+1

クラスの場合は、クラス変数を割り当てることでそれを行うことができます。 – Thameem

答えて

2

それが正しいトリッキーになりますなってもはい、これを行う方法があります。 inspectモジュールを使用すると、コールスタックにアクセスできます。これにより、関数と呼ばれるコードの外観を見ることができます。最後のエントリに二

[(<frame object at 0x107de1d38>, 'path/to/function/file.py', 6, 'func', ['\tstack = inspect.stack()\n'], 0), (<frame object at 0x107d34050>, 'path/to/calling/file.py', 17, '<module>', ['func()\n'], 0)] 

お知らせ:['func()\n']

スタックは次のようになります。これはあなたの関数を呼び出すコードを示しています。関数の名前はスタック内の他の場所にも表示されますが、呼び出される方法に関係なく関数の実際の名前が常に表示されます。コールが直接に、または割り当てられた変数を介して行われたかどうかを判断するには、自分で少し仕事をしなければなりません。

これは、関数名を取得する唯一の方法です。 Python does not have a featureを使用して、関数自体から関数名を取得します。

これはちょうどif func_name in stackよりも難しいことを明らかにするために、関数を呼び出す方法とそれがどのように表示されるかの実際の例をいくつか示しています。関数は独自の名前を判別できないため、関数の先頭にハードコーディングされています。

import inspect 


def func(var=None, default=''): 
    my_name = 'func' 
    stack = inspect.stack() 
    func_call = stack[-1][4][0] 
    print func_call.rstrip() # `func_call` contains a trailing newline 

    # logic to determine if the name matches 
    # ... 
    # ... 


x = func 
func() 
return_value = x(var=1) 
print func() 
if x(): 
    pass 

この版画:ここ

func() 
return_value = x(var=1) 
print func() 
None # This prints from the call, because `func()` doesn't return anything 
if x(): 
+0

質問に答えられない場合、これはどのように受け入れられた回答ですか?名前を取得するには関数が呼び出され、結果行が名前に割り当てられるかどうかを判断するにはソース行では不十分です。 – BlackJack

+0

@BlackJackそれは十分な情報です、あなたはそれのための独自のロジックを書く必要があります。呼び出しはそこにあり、名前はそこにある。名前がコールに含まれているかどうかを判断する方法は、あなた次第です。 –

+0

@BlackJack私は関数が失敗しないようにする必要はありませんでした。この答えは、私が私の質問で説明した結果を正確に生成する要素を与えました。関数が他のケースで使用できないという事実は、私の質問とは無関係ですが、注目すべき価値があります。 – Seb

0

は、私は受け入れ答えに基づいて書いて実行している例です。関数に新しい名前を割り当てることはできませんが、私がやりたいことをします。

import inspect 

# generator function to get all the strings in an iterable object 
def descend_strings(obj): 
    if hasattr(obj,'__iter__'): 
     if type(obj)==dict: 
      for key in obj: 
       for result in descend_strings(obj[key]): 
        yield result 
     else: 
      for item in obj: 
       for result in descend_strings(item): 
        yield result 
    if type(obj)==str: 
     yield obj 

def func(): 
    stack = inspect.stack() 

    joined_flat_stack_str = ''.join(list(descend_strings(stack))) 

    if ('= func()' in joined_flat_stack_str) or ('print func()' in joined_flat_stack_str): 
     return 5 
    else: 
     print 'not assigned' 


func()  # 'not assigned' 
a = func() 
print a  # 5 
print func() # 5 

x = func 
x()   # 'not assigned' 
a = x()  # 'not assigned' 
print a  # None 
+0

かなり限られています。 'a、b = spam()、func()'または 'x = spam(func))'は戻り値が割り当てられているが使用されているが検査では認識されない場合です。その 'func()'には本当に奇妙で驚くべきAPIがあります。 – BlackJack

関連する問題