如何在python中增强内置函数的功能?

use*_*873 1 python python-2.7 python-3.x

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

例如

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

>>> sum([4,5,6,7]) #22
Run Code Online (Sandbox Code Playgroud)

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

例如

>>> sum(['s','t','a','c','k']) # 'stack'
Run Code Online (Sandbox Code Playgroud)

提前致谢

aba*_*ert 12

你不能像类,对象,模块等那样真正"monkeypatch"一个函数.

其他所有东西最终都归结为属性集合,因此用不同的属性替换一个属性或添加新属性既简单又有用.另一方面,功能基本上是原子的.*

当然,您可以通过替换sum函数来monkeypatch内置模块.但我不认为这就是你所要求的.(如果你是,见下文.)

无论如何,你不能修补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)
Run Code Online (Sandbox Code Playgroud)

这里唯一真正的问题是start,对吗?reduce允许你保留起始值,它将从iterable中的第一个值开始:

>>> reduce(operator.add, ['s', 't', 'a', 'c', 'k'])
'stack'
Run Code Online (Sandbox Code Playgroud)

那是sum不可能做到的.但是,如果你真的想,你可以重新定义sum可以:

>>> def sum(iterable):
...     return reduce(operator.add, iterable)
Run Code Online (Sandbox Code Playgroud)

… 要么:

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

但请注意,sum对于整数而言,这将比原始序列慢得多,并且它将引发一个TypeError而不是返回0空序列,依此类推.


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

import builtins
builtins.sum = _new_sum
Run Code Online (Sandbox Code Playgroud)

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

在2.x中,调用模块__builtin__.关于它如何通过全局变量访问的规则在2.3左右变化,在3.0中再变化.查看builtins/ __builtin__了解详情.


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

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


Ash*_*ary 5

不是猴子修补,只是重新定义sum,以使其适用于字符串.

>>> import __builtin__
def sum(seq, start = 0):
    if all(isinstance(x,str) for x in seq):
        return "".join(seq)
    else:
        return __builtin__.sum(seq, start)
...     
>>> sum([4,5,6,7])
22
>>> sum(['s','t','a','c','k'])
'stack'
Run Code Online (Sandbox Code Playgroud)