Сопоставить или применить функцию к одному значению - правильный способ сделать это в Python 3 - PullRequest
0 голосов
/ 22 февраля 2019

В моем проекте на python im во многих местах появляется функциональность, строго эквивалентная:

def map_or_single(item,func, iterative_classes, *args ):

   if isinstance(item, iterative_classes):
       for k in item:
           func(k, *args)
       return
   func(item, *args)

, но я уверен, что для этой тривиальной задачи должна быть встроенная функция Python (3?), ЯНе хочу изобретать велосипед и использовать это дерьмо в проекте.Кто-нибудь знает правильную встроенную функцию для этого?

Ответы [ 4 ]

0 голосов
/ 23 февраля 2019

Вы можете использовать функции map() и partial():

from functools import partial
from operator import add

l = [1, 2, 3]

result = map(partial(add, 2), l)

print(list(result))
# [3, 4, 5]
0 голосов
/ 22 февраля 2019

Я почти уверен, что для этого нет встроенного однострочного.У меня есть эта вспомогательная функция в моем проекте;

def any2list(val):
    if isinstance(val, (str, bytes)):
        val = [val]
    try:
        iter(val)
    except TypeError:
        val = [val]
    return list(val)

Цель этой функции - преобразовать любой ввод в list.Если указан один элемент, он возвращает список этого одного элемента.

Я использую это в других функциях, подобных этому,

def map_or_single(container, func, *args):
    container = any2list(container)
    for k in container:
        func(k, *args)

, и теперь аргумент container может быть правильным типом контейнера (например, list) или это может быть один элемент(скаляр) как int.Я нахожу эту стратегию довольно чистой, так как я не беспокоюсь о случае одного элемента.

Примечание: я выбираю обработку str s и bytes специально, чтобы any2list не разделяло словоили предложение отдельными буквами, что почти всегда то, что я хочу.Ваши варианты использования могут отличаться.

0 голосов
/ 23 февраля 2019

Это чистый антипаттерн , поэтому в Python не существует "правильного" или "правильного" способа сделать это (или большинство, если не все другие языки).Вы наверняка можете предложить широкий спектр хрупких решений, но это тот тип вещей, который в долгосрочной перспективе приводит к ошибкам, приносящим очень мало пользы.

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

Вместо этого интерфейса:

map_or_single(single, func, ...)
map_or_single(iterable, func, ...)

У вас есть этот интерфейс:

map_or_single([single], func, ...)
map_or_single(iterable, func, ...)

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

И, очевидно, если ситуация позволяет:

func(single)
map(func, iterable)
0 голосов
/ 22 февраля 2019

Не пытайтесь писать это вообще.Вместо

map_or_single(item, func, ...)

просто напишите

def mapper(func, items, *args):
    for k in items:
        func(k, *args)

mapper всегда принимает список (или какой-либо другой итеративный); вызывающий абонент может предоставить его в случае необходимости.

mapper(f, [1,2,3,4])
mapper(f, [1])  # Not mapper(f, 1)
mapper(f, some_tree_object.depth_first_iterator())
mapper(f, some_tree_object.breadth_first_iterator())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...