5

好奇心のためにこれ
を知りたい..内部関数のスコープが外部関数本体のみに制限されていることは知っていますが、スコープ外の内部関数変数にアクセスしたり、外部関数を呼び出したりする方法はまだありますその範囲?

In [7]: def main():
   ...:     def sub():
   ...:         a=5
   ...:         print a
   ...:         

In [8]: main()

In [9]: main.sub()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/dubizzle/webapps/django/dubizzle/<ipython-input-9-3920726955bd> in <module>()
----> 1 main.sub()

AttributeError: 'function' object has no attribute 'sub'

In [10]: 
4

5 に答える 5

7
>>> def main():
...     def sub():
...         a=5
...         print a
... 
>>> main.__code__.co_consts
(None, <code object sub at 0x2111ad0, file "<stdin>", line 2>)
>>> exec main.__code__.co_consts[1]
5
于 2012-07-24T07:33:07.240 に答える
4

内部関数を値として返すとできます

>>> def main():
...     def sub():
...         a = 5
...         print a
...     return sub
...
>>> inner = main()
>>> inner()
5

または、プロパティとして main にアタッチすることもできます (結局、関数はオブジェクトです)。

>>> def main():
...     def sub():
...         a = 5
...         print a
...     main.mysub = sub
...
>>> main()
>>> main.mysub()
5

ただし、コードを読んでいる人はほぼ確実に驚かれるため、これを行う非常に正当な理由を文書化することをお勧めします:-)

于 2012-07-24T07:28:25.020 に答える
1

関数はPythonの単なる別のオブジェクトであり、内省することができます。

実行時に外部関数本体を取得し、それを解析/評価して、現在の名前空間で関数を使用できるようにすることができます。

>>> import inspect
>>> def outer():
        def inner():
            print "hello!"
>>> inspect.getsourcelines(outer)
([u'def outer():\n', u'    def inner():\n', u'        print "hello!"\n'], 1)

external.inner()を呼び出すことと実際には同じではありませんが、外部関数のスコープ外で内部関数を明示的に使用可能にしない場合は、それが唯一の可能性だと思います。

たとえば、非常に単純な評価の試みは次のようになります。

>>> exec('\n'.join([ line[4:] for line in inspect.getsourcelines(outer)[0][1:] ]))
>>> inner()
hello!
于 2012-07-24T07:46:15.140 に答える
1

いいえ、できません。内部関数は外部関数の属性ではありません。

内部関数は、そのdefステートメントが実行された後 (外部関数が実行されている間) にのみ存在し、関数が終了すると存在しなくなります。

returnもちろん、内部関数も可能です。

于 2012-07-24T07:29:17.110 に答える
0

内部関数は、他の関数と同様に単なるローカル変数であるため、同じ規則が適用されます。アクセスしたい場合は、返却する必要があります。

于 2012-07-24T07:34:09.423 に答える