在python中是否有内置的标识功能?

时间:2012-01-05 18:49:28

标签: python python-3.x python-2.7

我想指出一个什么都不做的功能:

def identity(*args)
    return args

我的用例是这样的

try:
    gettext.find(...)
    ...
    _ = gettext.gettext
else:
    _ = identity

当然,我可以使用上面定义的identity,但内置肯定会运行得更快(并避免我自己引入的错误)​​。

显然,mapfilter使用None作为标识,但这是针对其实现的。

>>> _=None
>>> _("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

8 个答案:

答案 0 :(得分:85)

进行更多研究,没有,在issue 1673203Raymond Hettinger said there won't be中询问了一项功能:

  

最好让人们写下自己的琐碎传递   并考虑签名和时间成本。

实际上,更好的方法是实现(lambda避免命名函数):

_ = lambda *args: args
  • 优点:采用任意数量的参数
  • 缺点:结果是参数的盒装版本

OR

_ = lambda x: x
  • 优点:不会更改参数的类型
  • 缺点:正好采用1个位置参数

答案 1 :(得分:18)

https://en.wikipedia.org/wiki/Identity_function中定义的标识函数接受一个参数并保持不变:

def identity(x):
    return x

如果您希望签名def identity(*args) 严格来说是一个身份函数,那么您要求的是什么,因为您希望它采用多个参数。没问题,但是当Python函数没有返回多个结果时你会遇到问题,所以你必须找到一种方法将所有这些参数塞进一个返回值。

通常的返回方式&#34;多个值&#34;在Python中是返回值的元组 - 从技术上讲,它是一个返回值,但它可以在大多数上下文中使用,就像它是多个值一样。但这样做意味着你得到了

>>> def mv_identity(*args):
...     return args
...
>>> mv_identity(1,2,3)
(1, 2, 3)
>>> # So far, so good. But what happens now with single arguments?
>>> mv_identity(1)
(1,)

快速修复 问题可以快速解决其他问题,正如此处的各种答案所示。

因此,总而言之,Python中没有定义身份函数,因为:

  1. 正式定义(单个参数函数)并不是很有用,而且写得很简单。
  2. 将定义扩展为多个参数通常没有明确定义,并且您最好定义自己的版本,以便按照您的需要为您的特定情况工作。
  3. 对于您的确切案例,

    def dummy_gettext(message):
        return message
    

    几乎可以肯定你想要的 - 一个具有相同调用约定并返回gettext.gettext的函数,它返回其参数不变,并且清楚地命名以描述它的作用以及它的用途要使用的。如果表演在这里是一个至关重要的考虑因素,我会非常震惊。

答案 2 :(得分:17)

你的工作正常。当参数的数量得到修复时,你可以使用这样的匿名函数:

lambda x: x

答案 3 :(得分:5)

不,没有。

请注意您的identity

  1. 相当于lambda * args:args
  2. 将它的args - 即

    In [6]: id = lambda *args: args
    
    In [7]: id(3)
    Out[7]: (3,)
    
  3. 因此,如果您想要真正的身份识别功能,可能需要使用lambda arg: arg

答案 4 :(得分:2)

Python中没有内置的标识函数。对Haskell's id function的模仿将是:

identity = lambda x, *args: (x,) + args if args else x

用法示例:

identity(1)
1
identity(1,2)
(1, 2)

由于identity除了返回给定的参数外不执行任何操作,因此我认为它不会比本机实现慢。甚至可能更快,因为它可以保存对本机函数的调用。

答案 5 :(得分:2)

如果速度无关紧要,则应该处理所有情况:

def identity(*args, **kwargs):
    if not args:
        if not kwargs:
            return None
        elif len(kwargs) == 1:
            return  kwargs.values()[0]
        else:
            return (*kwargs.values(),)
    elif not kwargs:
        if len(args) == 1:
            return args[0]
        else:
            return args
    else:
        return (*args, *kwargs.values())

用法示例:

print(identity())
None
$identity(1)
1
$ identity(1, 2)
(1, 2)
$ identity(1, b=2)
(1, 2)
$ identity(a=1, b=2)
(1, 2)
$ identity(1, 2, c=3)
(1, 2, 3)

答案 6 :(得分:1)

单参数函数的存根

gettext.gettext(OP的示例用例)接受单个参数message。如果需要存根,则没有理由返回[message]而不是messagedef identity(*args): return args)。因此两者

_ = lambda message: message

def _(message):
    return message

非常合适。

  

...但内置肯定会运行得更快(并避免我自己引入的错误)​​。

这种微不足道的案件中的漏洞几乎无关紧要。对于预定义类型的参数,例如str,我们可以使用str()本身作为标识函数(因为string interning它甚至保留了对象标识,请参阅下面的id注释)并将其性能与lambda解决方案进行比较:

$ python3 -m timeit -s "f = lambda m: m" "f('foo')"
10000000 loops, best of 3: 0.0852 usec per loop
$ python3 -m timeit "str('foo')"
10000000 loops, best of 3: 0.107 usec per loop

微观优化是可能的。例如,以下Cython代码:

test.pyx

cpdef str f(str message):
    return message

然后:

$ pip install runcython3
$ makecython3 test.pyx
$ python3 -m timeit -s "from test import f" "f('foo')"
10000000 loops, best of 3: 0.0317 usec per loop

内置对象标识功能

不要将身份功能与id内置函数混淆,后者会返回&#39;身份&#39;对象(表示该特定对象的唯一标识符,而不是该对象的值,与==运算符相比),它在CPython中的内存地址。

答案 7 :(得分:-2)

线程很老了。但仍想发布此内容。

可以为参数和对象构建标识方法。在下面的示例中,ObjOut是ObjIn的标识。上面的所有其他例子都没有涉及dict ** kwargs。

class test(object):
    def __init__(self,*args,**kwargs):
        self.args = args
        self.kwargs = kwargs
    def identity (self):
        return self

objIn=test('arg-1','arg-2','arg-3','arg-n',key1=1,key2=2,key3=3,keyn='n')
objOut=objIn.identity()
print('args=',objOut.args,'kwargs=',objOut.kwargs)

#If you want just the arguments to be printed...
print(test('arg-1','arg-2','arg-3','arg-n',key1=1,key2=2,key3=3,keyn='n').identity().args)
print(test('arg-1','arg-2','arg-3','arg-n',key1=1,key2=2,key3=3,keyn='n').identity().kwargs)

$ py test.py
args= ('arg-1', 'arg-2', 'arg-3', 'arg-n') kwargs= {'key1': 1, 'keyn': 'n', 'key2': 2, 'key3': 3}
('arg-1', 'arg-2', 'arg-3', 'arg-n')
{'key1': 1, 'keyn': 'n', 'key2': 2, 'key3': 3}