Подтвердить что ты не робот

Как вызвать тот же метод для списка объектов?

Предположим, что такой код:

class Base:
    def start(self):
        pass
    def stop(self)
        pass

class A(Base):
    def start(self):
        ... do something for A
    def stop(self)
        .... do something for A

class B(Base):
    def start(self):

    def stop(self):

a1 = A(); a2 = A()
b1 = B(); b2 = B()

all = [a1, b1, b2, a2,.....]

Теперь я хочу вызвать методы start и stop (возможно, другие) для каждого объекта в списке all. Есть ли какой-нибудь элегантный способ для этого, кроме написания множества функций, таких как

def start_all(all):
    for item in all:
        item.start()

def stop_all(all):
4b9b3361

Ответ 1

Функции * _all() настолько просты, что для нескольких методов я просто написал функции. Если у вас много одинаковых функций, вы можете написать общую функцию:

def apply_on_all(seq, method, *args, **kwargs):
    for obj in seq:
         getattr(obj, method)(*args, **kwargs)

Или создайте функцию factory:

def create_all_applier(method, doc=None):
    def on_all(seq, *args, **kwargs):
        for obj in seq:
            getattr(obj, method)(*args, **kwargs)
    on_all.__doc__ = doc
    return on_all

start_all = create_all_applier('start', "Start all instances")
stop_all = create_all_applier('stop', "Stop all instances")
...

Ответ 2

Это будет работать

all = [a1, b1, b2, a2,.....]

map(lambda x: x.start(),all)    

простой пример

all = ["MILK","BREAD","EGGS"]
map(lambda x:x.lower(),all)
>>>['milk','bread','eggs']

и в python3

all = ["MILK","BREAD","EGGS"]
list(map(lambda x:x.lower(),all))
>>>['milk','bread','eggs']

Ответ 3

Похоже, что это будет более питонический способ сделать это, но я еще не нашел его.

Я иногда использую "карту", ​​если я вызываю одну и ту же функцию (а не метод) на кучу объектов:

map(do_something, a_list_of_objects)

Это заменяет кучу кода, который выглядит так:

 do_something(a)
 do_something(b)
 do_something(c)
 ...

Но также может быть достигнуто с помощью пешехода "for":

  for obj in a_list_of_objects:
       do_something(obj)

Недостатком является то, что a) вы создаете список как возвращаемое значение из "карты", которое просто выбрасывается, и б) он может быть более запутанным, чем просто простой вариант цикла.

Вы также можете использовать понимание списка, но это также немного оскорбительно (еще раз, создав список отбрасывания):

  [ do_something(x) for x in a_list_of_objects ]

Для методов я полагаю, что любой из них будет работать (с теми же оговорками):

map(lambda x: x.method_call(), a_list_of_objects)

или

[ x.method_call() for x in a_list_of_objects ]

Итак, на самом деле, я думаю, что пешеходный (но эффективный) цикл "для", вероятно, лучший выбор.

Ответ 4

Подход

for item in all:
    item.start()

прост, понятен и понятен. Это основной подход, который Python обеспечивает для этой операции. Вы можете, конечно, инкапсулировать его в функцию, если это что-то помогает. Определение специальной функции для этого для общего использования, вероятно, будет менее понятно, чем просто написать цикл for.

Ответ 5

возможно map, но поскольку вы не хотите создавать список, вы можете написать свой собственный...

def call_for_all(f, seq):
    for i in seq:
        f(i)

то вы можете сделать:

call_for_all(lamda x: x.start(), all)
call_for_all(lamda x: x.stop(), all)

Кстати, все это встроенная функция, не перезаписывайте ее, -)

Ответ 6

Взяв @Ants Aasmas ответьте еще на один шаг, вы можете создать оболочку, которая принимает вызов любого метода и пересылает ее ко всем элементам данного списка:

class AllOf:
    def __init__(self, elements):
        self.elements = elements
    def __getattr__(self, attr):
        def on_all(*args, **kwargs):
            for obj in self.elements:
                getattr(obj, attr)(*args, **kwargs)
        return on_all

Затем этот класс можно использовать следующим образом:

class Foo:
    def __init__(self, val="quux!"):
        self.val = val
    def foo(self):
        print "foo: " + self.val

a = [ Foo("foo"), Foo("bar"), Foo()]
AllOf(a).foo()

Что производит следующий вывод:

foo: foo
foo: bar
foo: quux!

С некоторой работой и изобретательностью она, вероятно, может быть улучшена для обработки атрибутов (возврат списка значений атрибутов).