Thursday, December 14, 2017

Is there a builtin identity function in python?

Leave a Comment

I'd like to point to a function that does nothing:

def identity(*args)     return args 

my use case is something like this

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

Of course, I could use the identity defined above, but a built-in would certainly run faster (and avoid bugs introduced by my own).

Apparently, map and filter use None for the identity, but this is specific to their implementations.

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

6 Answers

Answers 1

Doing some more research, there is none, a feature was asked in issue 1673203 And from Raymond Hettinger said there won't be:

Better to let people write their own trivial pass-throughs and think about the signature and time costs.

So a better way to do it is actually (a lambda avoids naming the function):

_ = lambda *args: args 
  • advantage: takes any number of parameters
  • disadvantage: the result is a boxed version of the parameters

OR

_ = lambda x: x 
  • advantage: doesn't change the type of the parameter
  • disadvantage: takes exactly 1 positional parameter

Answers 2

yours will work fine. When the number of parameters is fix you can use an anonymous function like this:

lambda x: x 

Answers 3

An identity function, as defined in https://en.wikipedia.org/wiki/Identity_function, takes a single argument and returns it unchanged:

def identity(x):     return x 

What you are asking for when you say you want the signature def identity(*args) is not strictly an identity function, as you want it to take multiple arguments. That's fine, but then you hit a problem as Python functions don't return multiple results, so you have to find a way of cramming all of those arguments into one return value.

The usual way of returning "multiple values" in Python is to return a tuple of the values - technically that's one return value but it can be used in most contexts as if it were multiple values. But doing that here means you get

>>> 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,) 

And fixing that problem quickly gives other issues, as the various answers here have shown.

So, in summary, there's no identity function defined in Python because:

  1. The formal definition (a single argument function) isn't that useful, and is trivial to write.
  2. Extending the definition to multiple arguments is not well-defined in general, and you're far better off defining your own version that works the way you need it to for your particular situation.

For your precise case,

def dummy_gettext(message):     return message 

is almost certainly what you want - a function that has the same calling convention and return as gettext.gettext, which returns its argument unchanged, and is clearly named to describe what it does and where it's intended to be used. I'd be pretty shocked if performance were a crucial consideration here.

Answers 4

No, there isn't.

Note that your identity:

  1. is equivalent to lambda *args: args
  2. Will box its args - i.e.

    In [6]: id = lambda *args: args  In [7]: id(3) Out[7]: (3,) 

So, you may want to use lambda arg: arg if you want a true identity function.

Answers 5

Stub of single-argument function

gettext.gettext (the OP's example use case) accepts single argument, message. If one needs a stub for it, there's no reason to return [message] instead of message (def identity(*args): return args). Thus both

_ = lambda message: message  def _(message):     return message 

fit perfectly.

...but a built-in would certainly run faster (and avoid bugs introduced by my own).

Bugs in such trivial case are barely relevant. About performance, for example, for a argument of predefined type, say str, we can use it as an identity function (because of string interning it even retains object identity, see id note below) and compare performance:

$ 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 

Some micro-optimisation is possible, but doesn't seem to worth it.

test.pyx

cpdef str f(str message):     return message 

Then:

$ 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 

Build-in object identity function

This should not be confused with id built-in function which returns:

the “identity” of an object.

Answers 6

The thread is pretty old. But still wanted to post this.

It is possible to build an identity method for both arguments and objects. In the example below, ObjOut is an identity for ObjIn. All other examples above haven't dealt with 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} 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment