Код запятой - автоматизировать скучные вещи


В настоящее время я работаю с помощью упражнений из главы 4 от автоматизации скучных вещей, который гласит:

"Скажите, у вас есть список значений такой: spam = ['apples', 'bananas', 'tofu', 'cats']

Написать функцию, которая принимает список в качестве аргумента и возвращает строку, в которой все элементы разделены запятой и пробелом, С и вставлен перед последним элементом. Например, пройдя предыдущий spam список функции вернутся 'apples, bananas, tofu, and cats'. Но ваша функция должна уметь работать с любым значением список передали ей".

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

spam = ['apples', 'bananas', 'tofu', 'cats']

def commaCode(listVar):
    if len(listVar) == 0: # condition for an empty list
        print('There are no items in this list.') 

    if len(listVar) == 1: # condition for a list with 1 item
        return (str(listVar[0])+'.')

    if len(listVar) == 2: # condition for a list with 2 items
        return (str(listVar[0]) + ' and ' + str(listVar[1]) + '.')

    if len(listVar) >=3: # conditions for lists with 3+ items
        listDisp = ''
        for i in range(len(listVar[:-1])):
            listDisp = listDisp + str(listVar[i]) + ', '
        listDisp = listDisp + 'and ' + str(listVar[-1])
        return (listDisp)

commaCode(spam)


4212
13
задан 10 апреля 2018 в 03:04 Источник Поделиться
Комментарии
6 ответов


  1. Вы хотите посмотреть на ул. присоединяйтесь

  2. в последнем случае len(listVar) выполняется 4 раза, что очень однообразная. Лучше установить его во временную переменную, и проверять, что каждый раз.

  3. Python имеет некоторые двоичные операторы удобство для обыденных вещей, как добавление. Вместо listDisp = listDisp + foo использовать listDisp += foo

  4. вместо вызова str() на все, как вы строите строку, почему бы не назвать ее впереди, поэтому она не может быть пропустил где-то по пути. Что-то вверху, как stringList = [ str(i) for i in listVar ] позволит устранить необходимость для всех тех str() звонки, разбросанных по всему коду.

  5. Именование: listVar это переменная. Для этого не нужно иметь 'ВАР(iable)' в своем названии. Как насчет 'inputList'? Имена важны - они послания в будущее (вы или тот, кто читает ваш код) о том, что вы/пытаетесь достичь. Аналогичная проблема с именем commaCode.

  6. range(len(listVar[:-1])) такой же, как и range(len(listVar)-1), который является одновременно легче читать, а можете воспользоваться пунктами 2 и до конца написаны как range(listVarLen-1) который, безусловно, понятнее.

Но в целом, для новичка, не плохо!

19
ответ дан 10 апреля 2018 в 03:04 Источник Поделиться

@pjz были очень хорошие моменты, поэтому я пропущу эти на мой комментарий.


  1. Как имена функций и имена переменных пишутся в snake_case в Python.

  2. Вместо того, чтобы печатать сообщение об ошибке, вызовет соответствующее исключение.

  3. Вы добавите период для ввода длины 1 и 2, но не дольше выходных.

  4. Используя список Python нарезки вы на самом деле можете удалить некоторые из ваших специальных случаев.

Вот две предлагаемые улучшения, легче и еще одна весть. Я также включил короткого тестирования фрагмент, чтобы проверить, что исключение.

def comma_code(input_list):
if len(input_list) == 0:
# Raise an exception rather than just printing the error
raise ValueError('List cannot be empty')
# Convert everything to string (could also raise an exception if not string)
string_list = [str(i) for i in input_list]
# Handle the trivial case
if len(string_list) == 1:
return string_list[0]

# This could be even more pythonic, but it would lose its readability
more_than_two_items = len(string_list) > 2
first_part = ', '.join(string_list[:-2])
optional_separator = ', ' * more_than_two_items
last_part = ', and '.join(string_list[-2:])

formatted_string = first_part + optional_separator + last_part
return formatted_string

def comma_code_pythonic(input_list):
if len(input_list) == 0:
raise ValueError('List cannot be empty')

string_list = [str(i) for i in input_list]

last_part = ', and '.join(string_list[-2:])
first_part = string_list[:-2]

formatted_string = ', '.join(first_part + [last_part])
return formatted_string

# Try to place non-global variables below the function
spam = ['apples', 'bananas', 'tofu', 'cats']

for i in range(5):
try:
print("comma_code:", comma_code(spam[:i]))
except ValueError as e:
print(repr(e))

for i in range(5):
try:
print("comma_code_pythonic:", comma_code_pythonic(spam[:i]))
except ValueError as e:
print(repr(e))

8
ответ дан 10 апреля 2018 в 09:04 Источник Поделиться

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

обратите внимание, на Python стиль руководства содействия snake_case за camelCase соглашения об именовании, поэтому я буду использовать вот эти.


"Скажем, у вас есть список значений, как это: кошки спам = ['яблоки', 'бананы', 'тофу','']

Написать функцию, которая принимает список значений в качестве аргумента и возвращает строку, в которой все элементы разделены запятой и пробелом, и вставлен перед последним элементом.

Что такое ключевые функции, которые нужно делать здесь?

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

Как выясняется, мы можем присоединиться к струнам с любой подстрокой мы любим, поэтому с помощью

', '.join(list_of_strings)

мы получаем следующее преобразование:

['apples', 'bananas', 'tofu', 'cats'] -> 'apples, bananas, tofu, cats'

Это почти все задачи! (присоединиться () ручки на 0 и 1 длины списка массивов правильно, поэтому вам не придется)
Нам просто нужно вставить 'and '.

Краткий анализ проблемы показывает, что мы только нужны 'and ' когда есть хотя бы два предмета, так что мы пишем модификации, чтобы сделать это.Мы могли бы просто добавить 'and' на предпоследнем месте в списке, но мы не хотим, чтобы в конечном итоге с ['x', 'y'] -> 'x, and, y' так что простое решение это заменить окончательный ввод в этом случае с 'and ' плюс ввода.

Мы можем сделать это с одной из следующих строк:

#python 2+:
list_of_strings[-1] = 'and %s' % list_of_strings[-1]
#python 2.6+:
list_of_strings[-1] = 'and {}'.format(list_of_strings[-1])
#python 3.6+:
list_of_strings[-1] = f'and {list_of_strings[-1]}'

Чтобы убедиться, что это не меняет входной сигнал (может быть повторно), мы должны сделать копию его первой. Самый простой способ это создать новый список с оригинала:

list_of_strings = list(input_list_of_strings)

Собрал все воедино, мы получим достаточно простую функцию в результате:

def comma_code(input_list_of_strings):
list_of_strings = list(input_list_of_strings)
if len(list_of_strings) > 1:
list_of_strings[-1] = f'and {list_of_strings[-1]}'
return ', '.join(list_of_strings)

3
ответ дан 10 апреля 2018 в 12:04 Источник Поделиться

Чтобы дополнить другие хорошие ответы уже даны, вот короткая версия, которая использует несколько из уже данной идеи, а также несколько дополнительных:

>>> spam = ['apples', 'bananas', 'tofu', 'cats']
>>> comma_code = lambda l: ", ".join(l[:-1] + ['and ' + l[-1]])
>>> comma_code(spam)
'apples, bananas, tofu, and cats'

В lambda статья представляет собой сокращенный метод определения небольших функций, а не полное def ... синтаксис.

Он также использует список нарезки, и обе строки и список конкатенации. Как долго, как вы знаете, ваш вклад в списке только строки, это должно быть хорошо, но если вы не уверены, особенно последний элемент в списке, один из подходов, используя .format() могли быть интегрированы так же хорошо.

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

2
ответ дан 10 апреля 2018 в 07:04 Источник Поделиться

>>> spam = ['apples', 'bananas', 'tofu', 'cats']
>>> print(', '.join(spam[:-2] + [spam[-2] + ' and ' + spam[-1]]))
apples, bananas, tofu and cats

Запятая после tofu не должно существовать.

Шаги:


  1. ', '.join(...) создает строку с разделителями-запятыми значений, содержащихся в spam

  2. spam[:-2] ломтики spam и создается подсписок от первого до второго до последнего элемента. Посмотрите на Python среза нотации.

  3. [spam[-2] + ' and ' + spam[-1]] создает список, содержащий: spam'ы предпоследний пункт ('tofu') слово 'and' и spam'ы последний пункт ('cats'). Создание списка необходимо, потому что Python не знаю, как объединить список + другой тип объекта. Мы можем только сцепляет списки.


Редактировать: Оксфордская запятая - это дело, видимо. Ну, ура-английски.

>>> spam = ['apples', 'bananas', 'tofu', 'cats']
>>> print(', '.join(spam[:-1] + [' and ' + spam[-1]]))
apples, bananas, tofu, and cats

0
ответ дан 10 апреля 2018 в 08:04 Источник Поделиться

Есть несколько прекрасных указатели на другие ответы, но я чувствую, что они пропускают самые подходящие для Python решение:

def comma_code(words):
*head, final = words

if head:
final = f'and {final}'

return ', '.join(*head, final)

Этот раствор должен быть достаточно ясен любому читателю, и мне читает как кодирование постановка задачи: дан непустой список слов, соединить их с запятой. Если есть больше чем один, добавить слово " и " перед последним словом.

Этот код не нуждается в особой пустой список, так как распаковка операция поднять ValueError на пустой ввод. Вы могли бы поймать и вернуть пустую строку, если это желаемое поведение, или вы могли бы использовать аргументы varadiac для уточнения интерфейс вот так:

def comma_code_args(first, *rest):
*head, final = first, *rest

if head:
final = f'and {final}'

return ', '.join(*head, final)

Это будет называться вот так:

>>> spam = ['apples', 'bananas', 'tofu', 'cats']

>>> comma_code(spam)
'apples, bananas, tofu, and cats'

>>> comma_code_args('apples', 'bananas', 'tofu', 'cats')
'apples, bananas, tofu, and cats'

>>> comma_code_args(*spam)
'apples, bananas, tofu, and cats'

0
ответ дан 11 апреля 2018 в 09:04 Источник Поделиться