如何猴子修补python列表__setitem__方法

bri*_*ice 5 python ctypes introspection

我想修补Python列表,特别是__setitem__用自定义代码替换方法.请注意,我不是要扩展,而是覆盖内置类型.例如:

>>> # Monkey Patch  
... # Replace list.__setitem__ with a Noop
...
>>> myList = [1,2,3,4,5]
>>> myList[0] = "Nope"
>>> myList
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

是的,我知道这对python代码来说是一个彻头彻尾的变态.不,我的用例并没有多大意义.尽管如此,它能做到吗?

可能的途径:

示范的例子

我实际上设法覆盖了方法本身,如下所示:

import ctypes

def magic_get_dict(o):
    # find address of dict whose offset is stored in the type
    dict_addr = id(o) + type(o).__dictoffset__
    # retrieve the dict object itself
    dict_ptr = ctypes.cast(dict_addr, ctypes.POINTER(ctypes.py_object))
    return dict_ptr.contents.value

def magic_flush_mro_cache():
    ctypes.PyDLL(None).PyType_Modified(ctypes.cast(id(object), ctypes.py_object))

print(list.__setitem__)
dct = magic_get_dict(list)
dct['__setitem__'] = lambda s, k, v: s
magic_flush_mro_cache()
print(list.__setitem__)

x = [1,2,3,4,5]
print(x.__setitem__)
x.__setitem__(0,10)
x[1] = 20
print(x)
Run Code Online (Sandbox Code Playgroud)

其中输出如下:

? python3 override.py
<slot wrapper '__setitem__' of 'list' objects>
<function <lambda> at 0x10de43f28>
<bound method <lambda> of [1, 2, 3, 4, 5]>
[1, 20, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

但是如输出中所示,这似乎不会影响设置项目的正常语法(x[0] = 0)

替代方案:猴子修补单个列表实例

作为一个较小的选择,如果我能够修补单个列表的实例,这也可以工作.也许通过将列表的类指针更改为自定义类.

jsb*_*eno 0

做不到。如果你确实强制使用 CType,那么你只会比其他任何东西都更快地崩溃 Python 运行时 - 因为许多东西本质上只是使用 Python 数据类型。