varargs в лямбде функционирует в Python

Функция лямбды действительно ли возможно иметь переменное количество аргументов? Например, я хочу записать метакласс, который создает метод для каждого метода некоторого другого класса, и этот недавно созданный метод возвращает противоположное значение исходного метода и имеет то же количество аргументов. И я хочу сделать это с функцией лямбды. Как передать аргументы? Действительно ли это возможно?

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

Но результат является полностью неправильным:

>>>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
23
задан brain_damage 26 May 2010 в 16:45
поделиться

2 ответа

Нет проблем с использованием переменных в лямбда-функциях. Проблема здесь в другом:

Проблема в том, что лямбда ссылается на переменную цикла v . Но к моменту вызова лямбда значение v изменилось, и лямбда вызывает неправильную функцию. Это всегда то, чего нужно остерегаться, когда вы определяете лямбду в цикле.

Вы можете исправить это, создав дополнительную функцию, которая будет хранить значение v в закрытии:

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)
32
ответ дан 29 November 2019 в 01:32
поделиться

Да.

>>> l = lambda *x: print(x)
>>> l(1,2,3)
(1, 2, 3)
19
ответ дан 29 November 2019 в 01:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: