2

楽しみのために、関数クラスコンストラクターを使用して、つまり言語コンストラクトdefを使用せずに、型オブジェクトをインスタンス化してクラスを作成するのと同じように関数を作成できるかどうかを知りたいと思います。関数コンストラクターは、コードオブジェクトとグローバルの2つの引数を取ります。しかし、ソースを適切にコンパイルする方法がわかりません。

>>> def f(): 
...     pass

>>> Function = type(f) 
>>> Function
<class 'function'>
>>> code = compile("x + 10", "<string>", "exec")
>>> f = Function(code, globals())
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'x' is not defined
>>> f(20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <module>() takes 0 positional arguments but 1 was given
4

2 に答える 2

4

co_varnames、co_nlocals など、コード オブジェクトに多くの属性を設定する必要があります。

code = compile("def foo(n):return n+10", "<string>", "exec").co_consts[0]
func = Function(code, globals())

しかし、これは不正行為と見なされると思います。実際にコード オブジェクトを最初から定義するには、次のようにします (3.3 の場合)。

code = types.CodeType(1, 0, 1, 2, 67, b'|\x00\x00d\x01\x00\x17S', (None, 10), 
                      (), ('x',), '<string>', 'f', 1, b'\x00\x01')
func = Function(code, globals())
print(func(10))

もちろん、これには compile() 全体を自分で行う必要があります。

于 2013-01-31T16:53:22.610 に答える
0

さて、これはうまくいきます:

>>> x = 0
>>> def f(): pass
... 
>>> func = type(f)
>>> code = compile("global x\nx += 10","<string>","exec")
>>> nf = func(code,globals())
>>> nf()
>>> x
10

ただし、関数に引数を渡す方法がわかりません。

于 2013-01-31T16:36:55.807 に答える