Szukałem podobnego filtrowania list, ale chciałem mieć nieco inny format niż to, co zostało tutaj przedstawione.
Powyższe połączenie jest dobre, ale ograniczone pod względem ponownego użycia. Szukałem czegoś bardziej podobnego do get_hats(get_clothes(all_things))
, gdzie można podać źródło (all_things)
, a następnie jak mało lub tyle poziomów filtrów, ile chcesz.
znalazłem sposób, aby to zrobić z generatorów:
def get_clothes(in_list):
for item in in_list:
if item.garment:
yield item
def get_hats(in_list):
for item in in_list:
if item.headgear:
yield item
ten może być następnie zwanych przez:
get_hats(get_clothes(all_things))
Testowałem oryginalne rozwiązania, rozwiązanie vartec i to dodatkowe rozwiązanie, aby zobaczyć wydajności i był nieco zaskoczony wynikami. Kod następująco:
Setup:
class Thing:
def __init__(self):
self.garment = False
self.headgear = False
all_things = [Thing() for i in range(1000000)]
for i, thing in enumerate(all_things):
if i % 2 == 0:
thing.garment = True
if i % 4 == 0:
thing.headgear = True
oryginalne rozwiązania:
def get_clothes():
return filter(lambda t: t.garment, all_things)
def get_hats():
return filter(lambda t: t.headgear, get_clothes())
def get_clothes2():
return filter(lambda t: t.garment, all_things)
def get_hats2():
return filter(lambda t: t.headgear and t.garment, all_things)
Moje rozwiązanie: rozwiązanie
def get_clothes3(in_list):
for item in in_list:
if item.garment:
yield item
def get_hats3(in_list):
for item in in_list:
if item.headgear:
yield item
vartec za:
def get_clothes4():
for t in all_things:
if t.garment:
yield t
def get_hats4():
for t in get_clothes4():
if t.headgear:
yield t
kod
Timing:
import timeit
print 'get_hats()'
print timeit.timeit('get_hats()', 'from __main__ import get_hats', number=1000)
print 'get_hats2()'
print timeit.timeit('get_hats2()', 'from __main__ import get_hats2', number=1000)
print '[x for x in get_hats3(get_clothes3(all_things))]'
print timeit.timeit('[x for x in get_hats3(get_clothes3(all_things))]',
'from __main__ import get_hats3, get_clothes3, all_things',
number=1000)
print '[x for x in get_hats4()]'
print timeit.timeit('[x for x in get_hats4()]',
'from __main__ import get_hats4', number=1000)
Wyniki:
get_hats()
379.334653854
get_hats2()
232.768362999
[x for x in get_hats3(get_clothes3(all_things))]
214.376812935
[x for x in get_hats4()]
218.250688076
Generator wyrażeń pojawiają się nieco szybciej, różnica w czasie pomiędzy rozwiązaniami moje i vartec są prawdopodobnie tylko szum. Ale wolę elastyczność w możliwości stosowania dowolnych filtrów w dowolnej kolejności.
Jeśli martwisz się o wydajność, czy ** sprawdziłeś ** wydajność? –
Miałbym, gdybym myślał, że to nie było oczywiste. – cammil
"oczywiste" to niebezpieczne słowo, jeśli chodzi o wydajność. –