在Python中可以像JavaScript一样原型化字符串函数吗

5 投票
1 回答
2249 浏览
提问于 2025-04-17 19:32

在JavaScript中,你可以这样做,把一个修剪(trim)功能添加到现有的原型函数里。

String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g,"");

然后你可以像这样来使用这些功能。

trimmed = myString.trim();

这样你就得到了一个修剪过的字符串。

在Python中,我知道可以通过这样的方法列出字符串的原型函数:

print dir(myString)

但是我该怎么在Python中添加一个原型函数呢?

1 个回答

14

首先,Python 是基于类的对象系统,而不是像 JavaScript 那样的基于原型的系统。

给一个类或实例添加方法(或者其他属性)是非常简单的:

FooClass.method = my_method
foo_instance.method = my_method

不过,这种方法对许多“内置”类型(真正的内置类型,以及那些在 C 扩展中定义的类型)是行不通的。而 str 就是其中之一。

所以,你不能这样做。


不过,几乎任何类型都可以很容易地创建一个子类:

class MyStringType(str):
    def trim(self):
        # your implementation here

你可能需要一个自定义的 __init__ 方法,还有可能需要一个自定义的 __new__ 方法。还要确保把所有返回 str 的方法改成返回 MyStringType


另一种方法是通过委托来实现:

class MyStringType(object):
    def __init__(self, *args, **kwargs):
        self.s = str(*args, **kwargs)
    def trim(self):
        # your implementation here

这样,你就需要明确地转发每一个想要从 str 中获取的方法,而不是自动获取。不过,这样做通常更好。特别是考虑到你可以很简单地通过实现一个自定义的 __getattr__,或者在 __init__ 中或类级别上编写转发方法来实现。


但最简单的解决方案是……干脆别这么做。为什么要让一个 trim 函数只接受 str 类型的参数呢?

这样做的好处是,你的 trim 函数可以接受任何类似字符串的对象。例如,你的 trim 函数(作为对某个编译正则表达式 rr.replace 的封装)可以同时处理 unicodebytes(在 Python 2.x 中,bytesstr 的同义词,而在 3.x 中则不是……但如果你能同时处理这两者,那就无所谓了),还可以处理 PyObjC 的 NSString 封装或 pywin32 的 BSTR 封装,等等。一个 find 类型的方法甚至可以在 mmap 区域上工作。为什么要限制它只能在 str 上工作呢?

这种“鸭子类型”是 Python 处理事情的核心。如果你的代码没有理由关心一个对象的实际类型,那就不必特意去关注它。

撰写回答