как применить функцию карты, когда список содержит элементы объектов класса?

#python

Вопрос:

Python 3.8

MRE:

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

 lst = [1, 2, 3, 4]
list(map(lambda x: x*2, lst))
 

Я хочу сделать то же самое, когда элементы lst являются объектами класса, и хочу запустить метод для каждого объекта класса. Я мог бы сделать это, используя цикл for, однако любопытно узнать, могу ли я использовать функцию map, поскольку она более эффективна.

 class test:
    def __init__(self, value):
        self.value = value
    def reset(self):
        self.value = 0

obj_lst = [test(1), test(2), test(3)]

# want to replace this with map function
for obj in obj_lst:
    obj.reset()
 

Я пытался

 map(lambda x:x.reset(), obj_lst)
 

однако это не работает.

Комментарии:

1. возвращайтесь self.value после self.value = 0 , потому что вывод функции сброса по умолчанию отсутствует, а Лямбда задает вывод функции

2. @jizhihaoSAMA Мой ожидаемый результат-сброс всех объектов тестового класса

Ответ №1:

return self.value после self.value = 0 , потому что вывод функции сброса по умолчанию отсутствует, и map функция задает вывод функции

 class Test:
    def __init__(self, value):
        self.value = value

    def reset(self):
        self.value = 0
        # return self.value

    @classmethod
    def show(cls, obj_list: list):
        print([obj.value for obj in obj_list])


obj_lst = [Test(1), Test(2), Test(3)]

# print("before", obj_lst[0].value)
# want to replace this with map function
for obj in obj_lst:
    obj.reset()

Test.show(obj_list=obj_lst)
#
# print(list(map(lambda x: x.reset(), obj_lst)))
#
# print("after ", obj_lst[0].value)
 

Комментарии:

1. Спасибо! Что делать, если я не хочу reset method ничего возвращать, но просто сброшу его объект?

2. Ваш код работает правильно, и вы можете написать a @classmethod , который принимает an object_list в качестве входных данных и отображает values его содержимое

Ответ №2:

В вашем первом примере, когда вы применили эту функцию, вы вернули результат ! это то, что возвращается при применении функции к отдельным элементам. Но теперь вы просто хотите что-то сделать с предметами и не заинтересованы в том, что возвращается! возвращаемое значение вашего reset метода равно None. Таким образом, вы просто заполняете список нулей.

 [None, None, None]
 

Ваш цикл for — лучший ответ.

Вы могли бы сделать это с list(map()) пониманием или перечислением, но это не даст вам эффективности, за исключением того, что он вернет список None s…

 class test:
    def __init__(self, value):
        self.value = value
    def reset(self):
        self.value = 0

obj_lst = [test(1), test(2), test(3)]

[i.reset() for i in obj_lst]

print(obj_lst[0].value)   # 0
 

По крайней мере, я не назначал его так, чтобы после операции этот список немедленно собирал мусор. Но опять же, в вашем цикле for нет ничего плохого.

Комментарии:

1. Спасибо! Я знаю, что в методе цикла нет ничего плохого, просто хочу знать альтернативные методы, если они есть.

Ответ №3:

Поскольку вы просто хотите запустить функцию reset() для каждого объекта, и эта функция не возвращает никаких значений, было бы лучше использовать этот for-loop подход.

Что map() делает ? Документы

Возвращает итератор, который применяет функцию к каждому элементу итерируемого.

Используйте map() , когда у вас есть функция, которая возвращает некоторые значения, и вам нужны эти значения.

Ответ №4:

Просто для петли достаточно.Потому что ваша функция ничего не возвращает.

Но если вы действительно хотите избавиться от них, у вас есть два решения:

  1. измените лямбда-функцию:
 list(map(lambda x: x.reset() or x, obj_lst))

# [<__main__.test at 0x1103baa90>, <__main__.test at 0x1103bad30>, <__main__.test at 0x1103ba5b0>]
 
  1. сделать return self в функции reset
 class test:
    def __init__(self, value):
        self.value = value
    def reset(self):
        self.value = 0
        return self

obj_lst = [test(1), test(2), test(3)]
list(map(lambda x: x.reset(), obj_lst))
# [<__main__.test at 0x1103baa90>, <__main__.test at 0x1103bad30>, <__main__.test at 0x1103ba5b0>]
 

И все эти значения обнулились до нуля.

Комментарии:

1. Спасибо. почему происходит сброс, когда мы оборачиваемся map(lambda x: x.reset(), obj_lst) списком?

2. @haneulkim это был итератор, прежде чем вы преобразовали его в список…..операция не будет выполнена.