python - 如何增强python中内置函数的特性?

标签 python python-2.7 python-3.x

我是 python 编程的新手, 我想知道如何增强内置函数的特性(Monkeypatch)

例如

我知道sum()内置函数只允许在数字项上使用

>>> sum([4,5,6,7]) #22

我想让 sum 函数允许项目列表作为字符串,如下所示

例如

>>> sum(['s','t','a','c','k']) # 'stack'

提前致谢

最佳答案

你不能像处理类、对象、模块等那样真正地“monkeypatch”一个函数。

那些其他的东西最终都归结为一组属性,因此用一个不同的属性替换一个属性,或者添加一个新的属性,既简单又有用。另一方面,函数基本上是原子的东西。*

当然,您可以通过替换 sum 函数来猴子修补内置模块。但我不认为那是你要问的。 (如果你是,请参阅下文。)

无论如何,你不能修补sum,但你可以编写一个新函数,如果你愿意的话可以使用相同的名称,(可能对原始函数进行包装——你将注意,这正是装饰器所做的)。


但确实没有办法使用 sum(['s','t','a','c','k']) 来做你想做的事,因为 sum 默认情况下从 0 开始并向其添加内容。而且你不能将字符串添加到 0.**

当然,您始终可以传递显式 start 而不是使用默认值,但是您必须更改调用代码以发送适当的 start。在某些情况下(例如,您要发送文字列表显示)这很明显;在其他情况下(例如,在通用函数中)它可能不是。这在这里仍然行不通,因为 sum(['s','t','a','c','k'], '') 只会引发一个 TypeError(尝试并阅读错误以了解原因),但在其他情况下它会起作用。

但无法避免使用 sum 知道合适的起始值,因为这就是 sum 的工作原理。

如果您考虑一下,sum 在概念上等同于:

def sum(iterable, start=0):
    reduce(operator.add, iterable, start)

这里唯一真正的问题是 start,对吧? reduce 允许您省略起始值,它将从可迭代对象中的第一个值开始:

>>> reduce(operator.add, ['s', 't', 'a', 'c', 'k'])
'stack'

这是 sum 做不到的。但是,如果您真的想要,您可以重新定义 sum,这样它可以:

>>> def sum(iterable):
...     return reduce(operator.add, iterable)

……或者:

>>> sentinel = object()
>>> def sum(iterable, start=sentinel):
...     if start is sentinel:
...         return reduce(operator.add, iterable)
...     else:
...         return reduce(operator.add, iterable, start)

但请注意,此 sum 在处理整数时比原来的要慢得多,并且会引发 TypeError 而不是返回 0在空序列上,依此类推。


如果您真的想对内置函数进行 monkeypatch(而不是仅仅定义一个具有新名称的新函数,或者在您的模块的 globals() 中定义一个具有相同名称的新函数来隐藏内置),这是一个适用于 Python 3.1+ 的示例,只要您的模块使用普通的全局字典(除非您在嵌入式解释器或 exec 调用或类似的情况下运行,否则它们将是):

import builtins
builtins.sum = _new_sum

换句话说,与 monkeypatching 任何其他模块相同。

在 2.x 中,该模块称为 __builtin__。通过全局变量访问它的规则在 2.3 左右发生了变化,在 3.0 中又发生了变化。参见 builtins/__builtin__了解详情。


* 当然这不是完全是真的。函数在其代码对象之上有一个名称、一个闭包单元列表、一个文档字符串等。甚至代码对象也是一系列字节码,您可以在其上使用 bytecodehacks 或硬编码 hackery。除了 sum 实际上是一个内置函数,而不是一个函数,所以它甚至没有可从 Python 访问的代码……无论如何,对于大多数用途来说,它已经足够接近于说函数是原子的东西。

** 当然,您可以将字符串转换为某个知道如何将自身添加到整数(通过忽略它们)的子类,但实际上,您不想这样做。

关于python - 如何增强python中内置函数的特性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17098423/

相关文章:

python - 正则表达式 findall 匹配字符串中的字母 "a"到 "z"后跟另一个字符

Python3关于字节变量的正则表达式

python - Ironpython:函数在 CPython 中工作,IronPython 中神秘的空指针异常

python - 使用 2 列的累积和

python - 赋值的右侧总是在赋值之前求值吗?

Python "in"range() 上的运算符时间复杂度

python - 大收件箱 : Too many arguments for command 上的 imaplib.select

python - 负实数的立方根

python - (初学者)第一个 Django Web 应用程序 - models.py

Python Pandas 查找所有值为 NaN 的行