Во время выполнения цикла один раз?

#python #list #function #while-loop

#python #Список #функция #цикл while

Вопрос:

Новичок в кодировании и пытаюсь решить эту проблему с кодированием, чтобы учиться.

Запрос:

Если мы перечислим все натуральные числа ниже 10, кратные 3 или 5, мы получим 3, 5, 6 и 9. Сумма этих кратных равна 23. Найдите сумму всех чисел, кратных 3 или 5, меньше 1000.

 three = []
five = []

def threeList():
    n = 1
    while (n*3<1000):
        result = n*3
        three.append(result)
        n  = 1
        return three

def fiveList():
    n = 1
    while (n*5<1000):
        result = n*5
        five.append(result)
        n  = 1
        return five

threeList()
fiveList()

print(three,five)
  

Это приводит к печати [3] [5] на консоль.

Ответ №1:

Ваш return является частью цикла, что означает, что в конце итерации вместо выполнения другой итерации вы просто return выходите из функции. Вывести его из цикла, т. Е.:

 def threeList():
    n = 1
    while (n*3<1000):
        result = n*3
        three.append(result)
        n  = 1
    return three
  

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

 def threeList():
    n = 1
    while (n*3<1000):
        result = n*3
        three.append(result)
        n  = 1
  

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

 def my_func(multiplier):
    result = []
    n = 1
    while (n*multiplier < 1000):
        result.append(n*multiplier)
        n  = 1
    return result
  

а затем замените

 threeList()
fiveList()
  

с

 three = my_func(3)
five = my_func(5)
  

На самом деле, вы могли бы объединить это с print() , поскольку для three и five нет другого применения, поэтому ваш окончательный код будет выглядеть следующим образом:

 def my_func(multiplier):
    result = []
    n = 1
    while (n*multiplier < 1000):
        result.append(n*multiplier)
        n  = 1
    return result

print(my_func(3), my_func(5))
  

Комментарии:

1. Я знал, что это было что-то настолько простое! Я прочитаю о области видимости переменной прямо сейчас. Спасибо!

2. Единственное, что я бы сделал, это то, что, хотя это правильно отражает предполагаемый результат OP, его реализация была неправильной в том смысле, который вы не исправили (дубликаты, вероятно, не следует добавлять дважды).). В противном случае отличный ответ 🙂

Ответ №2:

В дополнение к фантастическому ответу Марчина обратите внимание, что вы также можете выполнить математику, для каких элементов использовать заранее, и полностью избежать while цикла. range твой друг здесь.

 multiples_of_five = range(5, 1001, step=5)
multiples_of_three = range(3, 1001, 3)
  

Поскольку range остановка является эксклюзивной, но мы хотим, чтобы все числа, кратные трем и пяти, были до 1000 включительно, вместо этого мы должны остановиться на 1001 . Это упрощает my_func то, что Марчин изложил выше.

 def list_multiples(n):
    result = []
    for i in range(n, 1001, n):
        result.append(i)
    return result
  

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

 def list_multiples(n):
    return list(range(n, 1001, n))
  

Оттуда мы можем найти числа, кратные пяти и кратные трем

 fives = list_multiples(5)
threes = list_multiples(3)
  

Приведение к set для удаления дубликатов (15 кратно как 5, так и 3, но не должно суммироваться дважды)

 all_nums = set(fives   threes)
  

И суммируем результат

 result = sum(all_nums)
  

Комментарии:

1. Во время YMMV я рассматриваю любой while цикл (кроме while True ) как запах кода. Определенно есть места для их использования, но в целом вы должны по возможности использовать for цикл.

2. Отличное объяснение. Постараюсь избегать циклов While в будущем. Вопрос о «While True». Используем ли мы это только тогда, когда хотим запускать функцию вечно?

3. @BenWallace в любое время, когда «состояние по умолчанию» должно выполняться в цикле, и только в исключительных случаях вы должны выходить из этого цикла. Обычно запрашивать пользовательский ввод таким образом ( while True: user_in = input("some prompt"); if is_valid(user_in): break )

Ответ №3:

Чтобы решить вашу проблему по-питоновски, используйте sum() с выражением генератора типа:

Код:

 sum(i for i in range(1000) if i % 5 == 0 or i % 3 == 0)
  

Тестовый код:

 max_num = 1000
print(sum(i for i in range(max_num) if i % 5 == 0 or i % 3 == 0))
  

Результаты:

 233168
  

Комментарии:

1. Это намного проще, чем моя попытка! Никогда не думал делать это так. Спасибо.

2. Хотя это правильно, это нельзя считать полезным ответом для новичка, не включая объяснение того, как работают genexps. Существующий ответ звучит так, будто это особенность sum , а не sum работа с выражением генератора.

3. @AdamSmith Вы уже предоставили «ответ новичка», разве этого недостаточно? Помните, что целью Stack Overflow является создание полезного хранилища информации в стиле QnA, и это не всегда означает потворство наименьшему общему знаменателю. Хотя некоторые дополнительные объяснения всегда полезны, их отсутствие не оправдывает здесь отрицательных голосов…

4. @coldspeed пожимание плечами возможно, вы правы, но это, по сути, ответ только для кода, который, хотя и не неправильный , определенно не является отличным.

5. @AdamSmith, я всегда считал, что ответ, представляющий собой одну строку кода, несколько неадекватен. Примите Python. Другие объяснили основную проблему с операционным кодом. Но почему бы не объяснить, как это сделать правильно? 20 строк кода можно заменить одной (ONE!) строка легко читаемого кода. Почему это плохо?