Список и генератор - ответственность вызывающих или функций

При вызове функции, которая принимает список, кто несет ответственность (вызывающий - пользователь или вызываемый - функция), чтобы убедиться, что это list , а не генератор ?

Пример:

>>> def print_collection(coll):
...     for element in coll:
...         print element

>>> def print_collection_twice(coll):
...     print_collection(coll)
...     print_collection(coll)

Со списком он будет работать без сюрпризов:

>>> print_collection_twice( [x*2 for x in xrange(3)] )
0
2
4
0
2
4

И с генератором, очевидно, он печатается только один раз, что может привести к неприятной ошибке:

>>> print_collection_twice( (x*2 for x in xrange(3)) )
0
2
4

Что такое лучшая практика здесь? Если функция принимает список, и пользователь отвечает за предоставление list , или если функция всегда всегда real_list = list (input_list) в начале, так что пользователь делает не волнует?

<Сильный> Edit

Я знаю , как проверить тип элемента и assert , мой вопрос довольно высокий

0

3 ответы

Любой подход оправдан. Функция document несет ответственность за , какие аргументы она хочет, а также ответственность вызывающего объекта передавать аргументы, соответствующие документации. Если функция говорит, что хочет список, и вы передаете генератор, нет никаких гарантий, что он будет работать.

Реальный вопрос заключается в том, что функция должна сказать , что она хочет, и ответ заключается в том, что он должен сказать только то, что ему нужно, и не более того. Поэтому не говорите, что вам нужен список, если все, что вам действительно нужно, является итерируемым. В общем случае, если вашей функции необходимо использовать функции списков, которые не имеют общих итераций (например, индексирование), тогда они должны просто использовать эти функции, и исключение, естественно, будет поднято, если кто-то передаст аргумент, который не поддерживать их. Если вашей функции не нужны эти функции, то ей не нужен список.

Ваш пример несколько нереалистичен, потому что все, что он делает, это распечатать аргумент. В реальной жизни вам почти всегда нужно что-то делать, кроме того, что вы просто уничтожаете итерацию, и природа этого «чего-то, что вам нужно сделать» прояснит, какой аргумент вы должны принять. Однако для вашего конкретного примера я бы сказал, что да, вызовите list на нем (внутри print_collection_twice , а не внутри print_collection )). Причина в том, что print_collection_twice хочет использовать данные более одного раза, что невозможно для универсального итерации.

3
добавлено

Лучшей практикой, безусловно, является document , что вам нужно. Документ, если аргумент должен быть итерируемым или последовательным. Философия Python заключается в использовании утиного ввода, поэтому вы должны просто попытаться использовать аргумент, как если бы это была последовательность.

Если вы хотите проверить, является ли аргумент последовательностью, простой способ сделать это без создания нового списка - это использовать встроенную функцию len :

>>> len(iter([1,2,3]))
Traceback (most recent call last):
  File "", line 1, in 
TypeError: object of type 'listiterator' has no len()

Если вы получите исключение, вы можете либо вызвать list , либо tuple , чтобы получить последовательность или разрешить исключение и позволить пользователю обрабатывать ее. Какая «политика» выбирать зависит, и это полностью зависит от вас. Программисты Python должны внимательно прочитать документацию и передать аргументы, которые будут работать хорошо, поэтому вы можете указать, что хотите, чтобы итерабельность была аргументом, и всегда вызывайте list для получения последовательности или укажите, что вы хотите последовательность и вызывать ошибку, если объект является итерируемым. Я не вижу смысла утверждать, что аргумент должен быть последовательностью, когда вы разрешаете также итерации.

Кстати, если вы просто хотите повторять несколько раз над итерируемым, вы можете использовать

«Лучшая практика - это, безусловно, документировать то, что вам нужно». Не согласен. Лучшая практика - неудача при неудачном вводе
добавлено автор Jakub M., источник
«Программистам Python следует внимательно прочитать документацию». <Код> s/Python/All/г
добавлено автор Jakub M., источник
Я могу принять частичное соглашение здесь ... document и не удается быстро
добавлено автор Jakub M., источник
@BrenBarn Я просто хотел указать на альтернативу. Я думаю, что ОП должен рассказать о возможных решениях и посмотреть, какой из них лучше подходит для его ситуации.
добавлено автор Bakuriu, источник
@JakubM. Да, неудача при неудачном вводе и дайте пользователю попробовать тысячи раз, чтобы получить точный формат, который принимает ваша функция?
добавлено автор Bakuriu, источник
itertools.tee - хорошая идея для общей проблемы, но для этого конкретного использования это не самое лучшее. Согласно документам : «В общем, если один итератор использует большинство или все данные перед запуском другого итератора, быстрее использовать list() вместо tee() . "
добавлено автор BrenBarn, источник

В моем oppinion это зависит от приложения внутри функции. Важно то, что вы document ли ваша функция принимает только списки или итераторы. Явный вызов list() внутри этой функции может вызвать избыточные издержки для длинных списков, что необязательно, если вы хотите только итерации по списку/генератору один раз.

0
добавлено
Вы можете попробовать len (argument) и посмотреть, вызывает ли это ошибку. Это не имеет больших накладных расходов и всегда должно работать.
добавлено автор Bakuriu, источник
Python
Python
7 654 участник(ов)

Уютный чат для профессионалов, занимающихся поиском питоньих мудростей. Как не получить бан: https://t.me/ru_python/577926

Python beginners
Python beginners
4 449 участник(ов)

Вопросы про Python для чайников. Cпам и троллинг неприемлем. Не злоупотребляйте стикерами. Частозадаваемые вопросы: https://github.com/ru-python-beginners/faq/blob/master/README.md Статистика тут: https://grstats.me/chat/x4qym2k5uvfkr3al6at7

pro.python
pro.python
1 090 участник(ов)

Сообщество разработчиков под Python Создатель: @rodgelius

Rude Python
Rude Python
971 участник(ов)

Python без „девочек”, здесь матерятся и унижают Django. Not gay friendly. Правила: t.me/rudepython/114107 @rudepython | t.me/rudepython

rupython
rupython
509 участник(ов)

Группа создана с целью оперативного получения ответов на возникающие вопросы по разработке на яп python, смежные темы, а также человеческого общения. Приветствую!

Python-programming
Python-programming
266 участник(ов)

Чат группы вконтакте https://vk.com/python_community