Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

varargs in lambda functions in Python

Is it possible a lambda function to have variable number of arguments? For example, I want to write a metaclass, which creates a method for every method of some other class and this newly created method returns the opposite value of the original method and has the same number of arguments. And I want to do this with lambda function. How to pass the arguments? Is it possible?

class Negate(type):     def __new__(mcs, name, bases, _dict):         extended_dict = _dict.copy()         for (k, v) in _dict.items():             if hasattr(v, '__call__'):                 extended_dict["not_" + k] = lambda s, *args, **kw:  not v(s, *args, **kw)         return type.__new__(mcs, name, bases, extended_dict)  class P(metaclass=Negate):     def __init__(self, a):         self.a = a      def yes(self):         return True      def maybe(self, you_can_chose):         return you_can_chose 

But the result is totally wrong:

>>>p = P(0) >>>p.yes() True >>>p.not_yes()     # should be False Traceback (most recent call last):   File "<pyshell#150>", line 1, in <module>     p.not_yes()   File "C:\Users\Desktop\p.py", line 51, in <lambda>     extended_dict["not_" + k] = lambda s, *args, **kw:  not v(s, *args, **kw) TypeError: __init__() takes exactly 2 positional arguments (1 given) >>>p.maybe(True) True >>>p.not_maybe(True)     #should be False True 
like image 391
brain_damage Avatar asked May 26 '10 16:05

brain_damage


People also ask

Can Python lambda take two arguments?

In Python, a lambda function is a single-line function declared with no name, which can have any number of arguments, but it can only have one expression.

How do you pass an n number argument in Python?

Yes. You can use *args as a non-keyword argument. You will then be able to pass any number of arguments. As you can see, Python will unpack the arguments as a single tuple with all the arguments.

What is variable length arguments in Python?

Variable-length arguments, varargs for short, are arguments that can take an unspecified amount of input. When these are used, the programmer does not need to wrap the data in a list or an alternative sequence. In Python, varargs are defined using the *args syntax.


1 Answers

There is no problem using varargs in lambda functions. The issue here is different:

The problem is that the the lambda refrences the loop variable v. But by the time the lambda is called, the value of v has changed and the lambda calls the wrong function. This is always something to watch out for when you define a lambda in a loop.

You can fix this by creating an additional function which will hold the value of v in a closure:

def create_not_function(v):     return lambda s, *args, **kw:  not v(s, *args, **kw)  for (k, v) in _dict.items():     if hasattr(v, '__call__'):         extended_dict["not_" + k] = create_not_function(v) 
like image 93
interjay Avatar answered Sep 28 '22 17:09

interjay