如何为 Python 原生对象添加函数
举个例子,我实现了一个过滤出字符串中所有数字的功能,函数名为filter_number,我想要附加到 str 对象上,这样调用函数可以写成"abc123abc".filter_number()。
我目前知道的做法就是新建对象继承 str ,但是调用前还是要手动转一遍s = CustomStr("abc123abc"),这就有点脱裤子放屁了。
不知道这个需求能不能实现,最好还要能被 ide 感知,编写时能够提示出来。
看样子应该是不行,初衷也只是为了调用函数时候能方便点,大部分函数功能是对字节和字符串做处理。 既然 Python 没有相关支持,那也没必要纠结下去,毕竟只是个锦上添花的操作。 #11 发的项目,名字就叫禁果,python 刚好还是条蛇。😂
省流:做不了,IDE 感知不到。
str 不知道 我知道 dict, 有一个 Userdict 是官方标准库提供的, 专门给用户干这事儿的.
pythonimport builtinsclass _CustomStr(str): def filter_number(self): passbuiltins.str = _CustomStr
对于显示声明为 str 的对象有效,但是对字面值无效:str("abc123abc").filter_number() # OK
`"abc123abc".filter_number()AttributeError: 'str' object has no attribute 'filter_number'
`
不知道 v2 code block 的语法,抱歉……
同关注C# 有 extension method 的语法糖,虽然实现方法也是类似于,新定义一个 Static Class ,包含一个 Static Method ,但调用方法就直接是用原生类型的实例去调用了Python 可能针对 str ,这种内置的对象,不行,没有这样的语法糖
在 Python 中,不能直接在 str 类型上添加自定义方法。但是,可以通过创建一个新的类来继承 str 类,并在新类中添加自定义方法。以下是一个示例:class MyStr(str): def my_custom_method(self): # 在这里实现你的自定义方法 pass# 使用自定义类my_str = MyStr("Hello, world!")my_str.my_custom_method()或者修改 str 的 built-in 方法一些常见对象的魔术方法__len__, __getitem__, __contains__, __add__, __mul__, __mod__, __format__, __eq__, __ne__, __lt__, __le__, __gt__, __ge__, __hash__, __repr__, __str__, __bytes__, __bool__, __int__, __float__, __complex__, __index__, __trunc__, __floor__, __ceil__, __round__, __enter__, __exit__, __new__, __init__, __del__, __call__, __getattr__, __setattr__, __delattr__, __dir__, __getattribute__, __setitem__, __delitem__, __iter__, __next__, __reversed__, __len__, __contains__, __add__, __mul__, __rmul__, __mod__, __format__, __eq__, __ne__, __lt__, __le__, __gt__, __ge__, __hash__, __repr__, __str__, __bytes__, __bool__, __int__, __float__, __complex__, __index__, __trunc__, __floor__, __ceil__, __round__, __enter__, __exit__, __new__, __init__, __del__, __call__, __getattr__, __setattr__, __delattr__, __dir__, __getattribute__, __setitem__, __delitem__, __iter__, __next__, __reversed__, __contains__, __add__, __mul__, __rmul__, __mod__, __format__, __eq__, __ne__, __lt__, __le__, __gt__, __ge__, __hash__, __repr__, __str__, __bytes__, __bool__, __int__, __float__, __complex__, __index__, __trunc__, __floor__, __ceil__, __round__, __enter__, __exit__, __new__, __init__, __del__, __call__, __getattr__, __setattr__, __delattr__, __dir__, __getattribute__, __setitem__, __delitem__, __iter__, __next__, __reversed__, __len__,
我自己的理解是做不到,不知道有没有什么奇淫巧技态添加函数可以有两种方式做到1. 继承2. 修改对象的内置属性而字符串是不可变的,2 做不到,只能是 1 ,也就是你说的“新建对象继承 str”字典是可以使用 2 的,因为字典是可变对象,但 UserDict 其实也是用继承
昨天刚问 Chatgpt 这个问题,已声明的倒是可以--在 Python 中,您可以使用 types.MethodType 将一个函数绑定到一个类的实例上。这允许您只为具体的实例添加函数,而不会更改整个类的定义。以下是一个示例:pythonimport typesclass MyClass: def __init__(self, value): self.value = value# 定义一个将要绑定的函数def print_value(self): print(self.value)# 创建一个 MyClass 的实例obj = MyClass(10)# 将函数绑定到这个实例obj.print_value = types.MethodType(print_value, obj)# 调用新绑定的函数obj.print_value()在上面的示例中,我们在 MyClass 的实例 obj 上绑定了 print_value 函数。具体细节如下:首先,我们定义了一个 MyClass 。该类包含了一个__init__构造函数,以及我们希望将其绑定的函数。我们定义了 print_value 函数,该函数接受一个参数 self ,它将打印 self.value 。然后,我们创建了 MyClass 的实例 obj ,并将要绑定的函数 print_value 绑定到了这个具体的实例上。最后,我们调用新绑定的函数:obj.print_value()。这样,我们就通过函数式编程功能将一个函数绑定到了 MyClass 的实例上。
没有语言能无副作用的直接为内置类型添加方法。如果你为 str 添加了方法 a ,lib b 也为 str 添加了方法 a 和 b ,那么调用 str.a() 的时候是调用你的 a 还是 lib b 的 a ?而且你直接调用 str.b() 的时候是给你提示 lib b 定义的 b 还是给你报错?这复杂度直接爆炸。现在的通用做法是,如果你要给 str 添加方法,那么你就定义一个新的类型,然后在自己定义的类型上定义方法。python 可以 class MyStr(str) 继承 str 。
给内置类型添加是不行的,但是搞一个类模拟函数,给函数添加是可以的class NamedFunction: def __init__(self, name, f): self.f = f self.name = name def __call__(self, args, kwargs): return self.f(args, kwargs) def __str__(self): return self.namef = NamedFunction("lambda: 'blah'", lambda: 'blah')print(f())print(f)
github.com/clarete/forbiddenfruit
或许可以换成 C++语言 :)
xy 问题
我敢打赌 楼主原来是写 js 的
你这 Python 怎么写得一股 Ruby 味啊(
修改 py 源码?
参考 8 楼,依稀记得 meta class 可以做到
标准库里提供了一个 collections.UserString ,专门方便你干这种事情的
github.com/xpodev/extype也不是完全不行,用原生扩展包里改
随便定义一个类型继承 str,写个空方法然后再使用的试试a:自定义类型 = ""或者typing 下 casta = cast(a,自定义类型)编辑器就可以自己识别了
如 #1 所说,没用,IDE 感知不到,但你非要骚操作的话:import gcd = gc.get_referents(str.__dict__)[0]d['show'] = lambda self: 'hello? are you okay?''foo'.show()# hello? are you okay?
不要魔改基础库,你改了用着爽了,别人怎么维护虽然此例能实现的话目前影响不大,但应该要以小见大,很多深坑都是一点点堆出来的
看#5, #14
#23 学到了。突然想起来这种有 vm 的语言本身是超级动态的🤔
在StackOverflow上有这样一个贴子,楼主说,我有下面这样的一个C++程序,为什么编译不通过啊。其让我想起了以前的这两个帖子《编程真难啊》和《给我一个序列号》。仅以此篇…
用了几天 win11 现在正式版出来了感觉还行,但是没有 win server 2022 流畅,一点不卡顿 弱弱的问一句 server 2022 怎么激活啊? #1 找微…
电脑重做了下系统,打算下个 7zip ,百度搜了一下 然后点了第一个,下载完发现需要付费购买永久会员??关键是这个盗版官网放的示例图 就是 7zip 和 他的官网地址而且还在用…