18

找不到更好的方法来表达标题,请随时更正。

我对 Python 还是很陌生,目前正在尝试使用这种语言。我注意到所有内置类型都不能用其他成员扩展。我想例如向该类型添加一个each方法list,但这会不可能。我意识到它是出于效率原因而设计的,并且大多数内置类型都是用 C 实现的。

好吧,我发现要覆盖此行为的一个原因是定义一个新类,该类扩展list但不执行任何操作。然后我可以将变量分配list给那个新类,每次我想实例化一个新列表时,我都会使用list构造函数,就像它被用来创建原始list类型一样。

class MyList(list):
    def each(self, func):
       for item in self:
           func(item)
list = MyList

my_list = list((1,2,3,4))
my_list.each(lambda x: print(x))

输出:

1
2
3
4

这个想法当然可以通过定义一个方法来概括,该方法获取一个构建的类型并返回一个扩展该类型的类。此外,原始list变量可以保存在另一个变量中以保持对其的访问。

我现在面临的唯一问题是,当您list通过其文字形式(即[1,2,3,4])实例化 a 时,它仍将使用原始列表构造函数(或者是吗?)。有没有办法覆盖这种行为?如果答案是否定的,您是否知道使用户能够扩展内置类型的其他方法?(就像 javascript 允许扩展内置原型一样)。

我发现内置函数的这种限制(无法向它们添加成员)是 Python 的缺点之一,使其与其他用户定义的类型不一致......总的来说,我真的很喜欢这种语言,我真的不明白为什么会这样限制是非常必要的。

4

1 回答 1

33

这是 Python 的良心选择。

首先,关于修补内置类型,这主要是设计决策,其次是优化。我从潜伏在 Python 邮件列表中的大量内容中了解到,猴子修补内置类型虽然对小型脚本来说很有趣,但在任何大型脚本中都没有任何用处。

一方面,图书馆对类型做出某些假设。如果鼓励扩展默认类型,许多库最终会互相争斗。它还会阻止创建新类型——双端队列是双端队列,有序集是有序集,字典是字典,应该是这样。

文字语法是一个特别重要的点。如果你不能保证那[1, 2, 3]是一个列表,你能保证什么?如果人们可以改变这些行为,它将产生全球影响,以至于破坏大量代码的稳定性。不鼓励使用goto和全局变量是有原因的。


不过,有一种特别的技巧是我喜欢的。当您看到 时r"hello",这似乎是一种扩展的文字形式。

那为什么不r[1, 2, 3]呢?

class ListPrefixer:
    def __init__(self, typ):
        self.typ = typ

    def __getitem__(self, args):
        return self.typ(args)

class MyList(list):
    def each(self, func):
        return MyList(func(x) for x in self)

e = ListPrefixer(MyList)

e[1, 2, 3, 4].each(lambda x: x**2)
#>>> [1, 4, 9, 16]

最后,如果你真的想做深入的 AST hack,请查看MacroPy

于 2013-09-29T21:24:07.770 回答