İşte bunu yapmanın bir yolu olarak geçirebilirsiniz. (@DSM tarafından belirtildiği gibi). Ne yazık ki sadece foo
işlevine atlayabiliyor ve sadece okunaklı oldukları için içeriden uzaklaşamıyoruz, yani yapmamız gereken, el ile oluşturduğumuz bir kopyasını değiştirmek.
# 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()
Ben bütün davaları yakalamayacaksin onun eminim.
- büyük argüman listesi CodeType geçirilen
- The: Ama bazı kadar düzenli yapabilirdi
Çirkin bit (eski piton 2.5.1 benim için) örneğin çalışır çirkin tuple, yalnızca bir üyeyi geçersiz kılan co_consts
'dan yapılmıştır. Tüm bilgiler, hangisinin değiştirileceğini belirlemek için co_consts içinde bulunur - bu yüzden daha akıllı bir işlev bunu yapabilir. İçine print(foo.func_code.co_consts)
kullanarak içten içe kazdım.
Sen tercüman komutunu help(types.CodeType)
kullanarak CodeType
ve FunctionType
hakkında bazı bilgiler bulabilirsiniz.
GÜNCELLEME: Bunun çok çirkin olduğunu düşündüm, bu yüzden daha güzel hale getirmek için yardımcı bir işlev oluşturdum. yardımcısı ile yazabilirsiniz: `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, {})
kullanılır:
İştemonkey_patch_fn
uygulanması var? Daha sonraki işlevlerde ('baz' gibi) kullanılır mı? Siz * bu vakalarda değiştirmek istersiniz? –Tam olarak. Bunu yapmanın herhangi bir yolu var mı? – Paolo
İşlevlerin çeşitli iç detaylarına erişebilirsiniz, çünkü bunlar sadece nesnelerdir. Daha fazla bilgi için dir işlevini ve dil referansını kullanın. – Marcin