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

306 天前
 lingeo

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

2576 次点击
所在节点    Python
26 条回复
abersheeran
306 天前
省流:做不了,IDE 感知不到。
chaleaochexist
306 天前
str 不知道
我知道 dict,
有一个 Userdict 是官方标准库提供的, 专门给用户干这事儿的.
capbone
306 天前
```python
import builtins


class _CustomStr(str):
def filter_number(self):
pass


builtins.str = _CustomStr
```

对于显示声明为 str 的对象有效,但是对字面值无效:

```
str("abc123abc").filter_number() # OK
```

```
"abc123abc".filter_number()

AttributeError: 'str' object has no attribute 'filter_number'
```
capbone
306 天前
不知道 v2 code block 的语法,抱歉……
McZoden
306 天前
同关注
C# 有 extension method 的语法糖,虽然实现方法也是类似于,新定义一个 Static Class ,包含一个 Static Method ,但调用方法就直接是用原生类型的实例去调用了
Python 可能针对 str ,这种内置的对象,不行,没有这样的语法糖
mightybruce
306 天前
在 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__,
CaptainD
306 天前
我自己的理解是做不到,不知道有没有什么奇淫巧技

态添加函数可以有两种方式做到
1. 继承
2. 修改对象的内置属性

而字符串是不可变的,2 做不到,只能是 1 ,也就是你说的“新建对象继承 str”

字典是可以使用 2 的,因为字典是可变对象,但 UserDict 其实也是用继承
kmyq
306 天前
昨天刚问 Chatgpt 这个问题,已声明的倒是可以
--
在 Python 中,您可以使用 types.MethodType 将一个函数绑定到一个类的实例上。这允许您只为具体的实例添加函数,而不会更改整个类的定义。以下是一个示例:

python
import types

class 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 的实例上。
zzhaolei
306 天前
没有语言能无副作用的直接为内置类型添加方法。如果你为 str 添加了方法 a ,lib b 也为 str 添加了方法 a 和 b ,那么调用 str.a() 的时候是调用你的 a 还是 lib b 的 a ?而且你直接调用 str.b() 的时候是给你提示 lib b 定义的 b 还是给你报错?这复杂度直接爆炸。

现在的通用做法是,如果你要给 str 添加方法,那么你就定义一个新的类型,然后在自己定义的类型上定义方法。

python 可以 class MyStr(str) 继承 str 。
mightybruce
306 天前
给内置类型添加是不行的,但是搞一个类模拟函数,给函数添加是可以的

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.name


f = NamedFunction("lambda: 'blah'", lambda: 'blah')
print(f())
print(f)
bytebuff
306 天前
c2const
306 天前
或许可以换成 C++语言 :)
Alias4ck
306 天前
xy 问题
lolizeppelin
306 天前
我敢打赌 楼主原来是写 js 的
msg7086
306 天前
你这 Python 怎么写得一股 Ruby 味啊(
bybyte
306 天前
修改 py 源码?
atuocn
306 天前
参考 8 楼,依稀记得 meta class 可以做到
MiketsuSmasher
306 天前
标准库里提供了一个 collections.UserString ,专门方便你干这种事情的
codehz
306 天前
https://github.com/xpodev/extype
也不是完全不行,用原生扩展包里改
bianhui
306 天前
随便定义一个类型继承 str,写个空方法
然后再使用的试试
a:自定义类型 = ""或者
typing 下 cast
a = cast(a,自定义类型)
编辑器就可以自己识别了

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

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

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

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

© 2021 V2EX