다음과 같은 코드를 가정하십시오.
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 메서드를 호출하고 싶습니다. 다음과 같은 많은 함수를 작성하는 것 외에는 우아한 방법이 있습니까?
def start_all(all):
for item in all:
item.start()
def stop_all(all):
답변
* _all () 함수는 매우 간단하여 몇 가지 메서드의 경우 함수를 작성하기 만하면됩니다. 동일한 함수가 많은 경우 일반 함수를 작성할 수 있습니다.
def apply_on_all(seq, method, *args, **kwargs):
for obj in seq:
getattr(obj, method)(*args, **kwargs)
또는 함수 팩토리를 만듭니다.
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")
...
답변
이것은 작동합니다
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']
답변
좀 더 파이썬적인 방법이있을 것 같지만 아직 찾지 못했습니다.
여러 객체에 대해 동일한 함수 (메서드가 아님)를 호출하는 경우 가끔 “맵”을 사용합니다.
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) 그냥 버려지는 “맵”에서 반환 값으로 목록을 만들고 b) 단순한 루프 변형보다 더 혼란 스러울 수 있다는 것입니다.
목록 이해력을 사용할 수도 있지만 약간 모욕적입니다 (다시 한 번 던져 버리는 목록 생성).
[ 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 ]
따라서 실제로는 보행자 (아직 효과적인) “for”루프가 아마도 최선의 방법이라고 생각합니다.
답변
접근
for item in all:
item.start()
간단하고, 쉽고, 읽기 쉽고, 간결합니다. 이것이 파이썬이이 작업을 위해 제공하는 주요 접근 방식입니다. 도움이된다면 함수에 확실히 캡슐화 할 수 있습니다. 일반적인 용도로이를위한 특수 함수를 정의하는 것은 for 루프를 작성하는 것보다 덜 명확합니다.
답변
어쩌면 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)
그건 그렇고, 모두 내장 함수이므로 덮어 쓰지 마십시오 😉
답변
Python 2.6부터 연산자가 있습니다. 함수가 있습니다.
따라서 더 우아하고 빠른 것을 얻을 수 있습니다.
from operator import methodcaller
map(methodcaller('method_name'), list_of_objects)
답변
@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 : 바 foo : quux!
약간의 작업과 독창성을 통해 속성도 처리하도록 향상 될 수 있습니다 (속성 값 목록 반환).