如何为 Python 原生对象添加函数

122 天前
 lingeo

举个例子,我实现了一个过滤出字符串中所有数字的功能,函数名为filter_number,我想要附加到 str 对象上,这样调用函数可以写成"abc123abc".filter_number()
我目前知道的做法就是新建对象继承 str ,但是调用前还是要手动转一遍s = CustomStr("abc123abc"),这就有点脱裤子放屁了。
不知道这个需求能不能实现,最好还要能被 ide 感知,编写时能够提示出来。

2286 次点击
所在节点    Python
26 条回复
frostming
122 天前
如 #1 所说,没用,IDE 感知不到,但你非要骚操作的话:

import gc

d = gc.get_referents(str.__dict__)[0]
d['show'] = lambda self: 'hello? are you okay?'
'foo'.show()
# hello? are you okay?
listenerri
122 天前
不要魔改基础库,你改了用着爽了,别人怎么维护

虽然此例能实现的话目前影响不大,但应该要以小见大,很多深坑都是一点点堆出来的
forgottencoast
121 天前
@zzhaolei
看#5, #14
zzhaolei
121 天前
@forgottencoast #23 学到了。突然想起来这种有 vm 的语言本身是超级动态的🤔
351994
119 天前
可以实现,aHR0cHM6Ly9ibG9nLnplYmVkeS5jb20vcG9zdC82Y2YyZTIwOS5odG1s
参考这里的,base64
351994
119 天前
是可以实现的,
import ctypes


class PyType(ctypes.Structure):
pass


class PyObject(ctypes.Structure):
Py_ssize_t = (
ctypes.c_int64 if ctypes.sizeof(ctypes.c_void_p) == 8 else ctypes.c_int32
)
_fields_ = [
("ob_refcnt", Py_ssize_t),
("ob_type", ctypes.POINTER(PyType)),
]


class PyTypeObject(PyObject):
_fields_ = [
("dict", ctypes.POINTER(PyObject))
]


def inject(class_, function_name):
def _(function):
name_, dict_ = class_.__name__, class_.__dict__
proxy_dict = PyTypeObject.from_address(id(dict_))
namespace = {}
ctypes.pythonapi.PyDict_SetItem(
ctypes.py_object(namespace),
ctypes.py_object(name_),
proxy_dict.dict
)
namespace[name_][function_name] = function

return _

可以参考#25 中的内容,发不了网址,base64 了一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1009891

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX