ここでそれを行うための一つの方法だとして、それを渡すことができます。 (@DSMのように)。残念ながら、foo
関数にジャンプして内部構造を混乱させることはほとんどありません。ほとんどの場合は読み取り専用となっているので、手作業で作成したコピーを変更するだけです。
私はすべてのケースをキャッチするつもりはないと確信しています。
- 巨大な引数リストがCODETYPE
に
- 渡される:しかし、それはアップし、いくつかのきちんとして行うことができます
醜いビットである(古いのpython 2.5.1に私のために)例えば働きますco_consts
から構成された醜いタプルは、1つのメンバーだけをオーバーライドします。すべての情報がco_constsに置き換えられるかどうかを判断するため、よりスマートな機能がこれを行うことができます。私はprint(foo.func_code.co_consts)
を使って手で内部を掘った。
あなたは通訳 コマンドhelp(types.CodeType)
を使用してCodeType
とFunctionType
に関するいくつかの情報を見つけることができます。
更新: これはあまりにも醜いと思ったので、私はそれをよりきれいにするヘルパー機能を構築しました。
# Use our function to get a new version of foo with "bar" replaced by mybar
foo = monkey_patch_fn(foo, "bar", my_bar)
# Check it works
foo()
ここmonkey_patch_fn
の実装があります:あなたが書くことができるヘルパーと
# Returns a copy of original_fn with its internal function
# called name replaced with new_fn.
def monkey_patch_fn(original_fn, name, new_fn):
#Little helper function to pick out the correct constant
def fix_consts(x):
if x==None: return None
try:
if x.co_name == name:
return new_fn.func_code
except AttributeError, e:
pass
return x
original_code = original_fn.func_code
new_consts = tuple(map(fix_consts, original_code.co_consts))
code_type_args = [
"co_argcount", "co_nlocals", "co_stacksize", "co_flags", "co_code",
"co_consts", "co_names", "co_varnames", "co_filename", "co_name",
"co_firstlineno", "co_lnotab", "co_freevars", "co_cellvars" ]
new_code = types.CodeType(
*[ (getattr(original_code,x) if x!="co_consts" else new_consts)
for x in code_type_args ])
return types.FunctionType(new_code, {})
'bar'使用される場合には?それは後の関数( 'baz'のようなもの?)で使われていますか?そういう場合にあなたは*置き換えたいでしょうか? –
正確に。それを行うには? – Paolo
functioneのさまざまな内部ディクショナリは、単なるオブジェクトなのでアクセスできます。詳細については、dir関数と言語リファレンスを使用してください。 – Marcin