def func(x):
if x>10:
return None
else:
return x*2
lst = [2, 4, 12, 7, 30, 3]
# original
result0 = [func(x) for x in lst if func(x) is not None]
# map... on Python 2.x, use itertools.imap()
result1 = [x for x in map(func, lst) if x is not None]
assert result1 == result0
# generator expression
result2 = [x for x in (func(y) for y in lst) if x is not None]
assert result2 == result0
# rewrite function as a generator function
def func_gen(iterable):
for x in iterable:
if x <= 10:
yield x*2
# no need to filter; filtering happens in generator function
result3 = list(func_gen(lst))
assert result3 == result0
# build a filtering generator out of parts
def fn_x2(x):
return x * 2
def filter_leq10(x):
return x <= 10
def make_filtering_gen_func(fn, flt, name="anonymous"):
def anonymous(iterable):
for x in iterable:
if flt(x):
yield fn(x)
anonymous.__name__ = name
return anonymous
func_gen1 = make_filtering_gen_func(fn_x2, filter_leq10)
result4 = list(func_gen1(lst))
assert result4 == result0
Комментарии.
@jamylak уже показал вам, как его решить map()
или itertools.imap()
. Но по какой-то причине он/она показал переписывание существующего списка, используя нарезку. Я не вижу причин для этого, поэтому я показал его с привязкой к имени переменной.
Наиболее часто рекомендуемая альтернатива map()
является выражением генератора, поэтому я показал, как использовать ее внутри понимания списка.
Но для таких случаев я обычно предпочитаю переписать функцию как генератор, который дает только нужные числа. Вы будете вызывать функцию в любом случае, поэтому вместо того, чтобы вернуть возвращаемое значение для нежелательных значений, просто получите только нужные значения.
И, наконец, функциональный способ создания фильтрующего генератора из деталей! Вы можете передать любую функцию, которая принимает один аргумент (и помните, что вы можете использовать functools.partial()
, чтобы связать другие аргументы и получить объект функции, который просто принимает один аргумент), плюс передать функцию фильтра, которая выбирает значения. Он создает объект функции и возвращает его, который автоматически обрабатывает «шаблонный» для вас, добавляя цикл for
, тест if
для фильтрации, а затем yield
с результатами.
спасибо - действительно ли imap дает какое-либо дополнительное преимущество перед картой? – IUnknown
@IUnknown Он возвращает итератор вместо списка. Это более эффективно для огромных наборов данных, для небольших списков вы не увидите большой разницы. – jamylak
Просто еще одна проблема - как я могу назвать карту для функции, которая принимает несколько дополнительных параметров - def func (x, множитель). – IUnknown