Какова общая практика с операторами возврата в функциях? - PullRequest
0 голосов
/ 21 января 2020

У меня проблемы с пониманием, когда использовать функцию return. В приведенной ниже функции моя интуиция заключается в том, что оператор return должен быть там, чтобы возвращать измененный список, но мой TA сказал, что это избыточно, что я не совсем понял, почему. Будем весьма благодарны за любые разъяснения о том, когда правильно использовать утверждение return и о обычной практике.

p = [2,0,1]
q = [-2,1,0,0,1,0,0,0]
p1 = [0,0,0,0]

#Without return statement
def drop_zeros1(p_list):
    """drops zeros at end of list"""
    i = 0 
    while i < len(p_list):
            if p_list[-1]==0:
                p_list.pop(-1)
            else:
                break

#With return statement
def drop_zeros(p_list):
    """drops zeros at end of list"""
    i = 0 
    while i < len(p_list):
            if p_list[-1]==0:
                p_list.pop(-1)
            else:
                return p_list
                break

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

Большое спасибо,

Ответы [ 2 ]

4 голосов
/ 21 января 2020

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

Это сделано для того, чтобы пользователь вашей функции не делал это :

template = [1, 2, 0, 0]
shorter = drop_zeros(template)
print ("input was ", template, " and output was ", shorter)

Они ожидают этого вывода:

вход был [1, 2, 0, 0], а выход был [1, 2]

... но удивитесь, увидев:

вход был [1, 2], а выход был [1, 2]

Так что, чтобы избежать этого, либо :

  • не вернет измененный аргумент, но None. Таким образом, вышеприведенный код выведет ...and output was None, и пользователь поймет, что функция не предназначена для возврата результата.

  • возвращает результат, но гарантирует, что аргумент сохраняет его исходное содержимое

Итак, в вашем случае вы можете сделать:

def drop_zeros(p_list):
    """drops zeroes at end of list, in-place"""
    while p_list and p_list[-1] == 0:
        p_list.pop()

Обратите внимание, что else может быть лучше интегрировано в условие while. Больше не нужно делать явное break. Также .pop() не требуется -1 в качестве аргумента: это значение по умолчанию.

Если вы предпочитаете функцию, которая возвращает результат, тогда логика c должна быть несколько другой:

def drop_zeros(p_list):
    """returns a copy of the list without the ending zeroes"""
    for i in range(len(p_list)-1, -1, -1):
         if p_list[i] != 0:
             return p_list[0:i+1]
    return []

Теперь код предназначен для:

template = [1, 2, 0, 0]
shorter = drop_zeros(template)
print ("input was ", template, " and output was ", shorter)
# input was [1, 2, 0, 0] and output was [1, 2]
0 голосов
/ 21 января 2020

Ваш TA прав, возврат избыточен из-за того, что в python называется aliasing .

В принципе, в вашей функции p_list является ссылкой (НЕ скопировать) в любой список, который вы передаете при вызове функции. Поскольку вы используете pop, который изменяет список на месте при извлечении элемента, p_list будет изменен, и эта модификация будет видна вне функции:

drop_zeros(q) # from here, in the function, p_list is q (as in, exactly the same object)
print(q)

печатает

[-2,1,0,0,1]
...