여기에 그 일을 한 가지 방법이기로에 전달할 수 있습니다. (@DSM에서 언급했듯이). 불행히도 우리는 단지 foo
함수로 뛰어 들며 내부적으로 엉망입니다. 대부분 읽기 전용으로 표시되어 있으므로 우리가 손수 작성하는 복사본을 수정해야합니다.
# Here's the original function
def foo():
def bar():
print(" In bar orig")
def baz():
print(" Calling bar from baz")
bar()
print("Foo calling bar:")
bar()
print("Foo calling baz:")
baz()
# Here's using it
foo()
# Now lets override the bar function
import types
# This is our replacement function
def my_bar():
print(" Woo hoo I'm the bar override")
# This creates a new code object used by our new foo function
# based on the old foo functions code object.
foocode = types.CodeType(
foo.func_code.co_argcount,
foo.func_code.co_nlocals,
foo.func_code.co_stacksize,
foo.func_code.co_flags,
foo.func_code.co_code,
# This tuple is a new version of foo.func_code.co_consts
# NOTE: Don't get this wrong or you will crash python.
(
foo.func_code.co_consts[0],
my_bar.func_code,
foo.func_code.co_consts[2],
foo.func_code.co_consts[3],
foo.func_code.co_consts[4]
),
foo.func_code.co_names,
foo.func_code.co_varnames,
foo.func_code.co_filename,
foo.func_code.co_name,
foo.func_code.co_firstlineno,
foo.func_code.co_lnotab,
foo.func_code.co_freevars,
foo.func_code.co_cellvars)
# This is the new function we're replacing foo with
# using our new code.
foo = types.FunctionType(foocode , {})
# Now use it
foo()
나는 모든 경우를 포착하지 않을 것이라고 확신합니다.
- 거대한 인수 목록이 CodeType에 전달되는
- :하지만 일부까지 깔끔와 함께 할 수있는
미운 비트 (오래된 파이썬 2.5.1에 나를 위해) 예 작동 co_consts
에서 생성 된 못생긴 튜플은 단 하나의 멤버를 무시합니다. 모든 정보는 co_consts로 대체 할 항목을 결정하므로 더 똑똑한 기능이이를 수행 할 수 있습니다. print(foo.func_code.co_consts)
을 사용하여 손으로 내부를 파 냈습니다.
당신은 인터프리터에게 명령 help(types.CodeType)
을 사용하여 CodeType
및 FunctionType
에 대한 몇 가지 정보를 찾을 수 있습니다.
업데이트 : 나는 이것이 너무 못 생겨서 내가 더 예쁘게 만드는 도우미 기능을 만들었다 고 생각했습니다. 도우미로 당신은 쓸 수 있습니다 :`bar`이
# 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, {})
을 사용 :
여기이
monkey_patch_fn
의 구현인가? 나중의 함수 (예 :'baz')에 사용됩니까? 당신은 * 그러한 경우에 그것을 바꿀 것입니다. 맞습니까? –정확히. 어떻게 할 수 있니? – Paolo
functione의 다양한 내부 다이어그램은 객체 일 뿐이므로 액세스 할 수 있습니다. 자세한 내용은 dir 함수 및 언어 참조를 사용하십시오. – Marcin