Разница между глобальной и локальной переменной - PullRequest
0 голосов
/ 28 декабря 2018

Я новичок в python и удивляюсь разнице между наличием пустого массива в качестве глобальной или локальной переменной при возврате массива.

import collections

def check_duplicates(data: list) -> list:
    dupes = []

    for i in data:
        if data.count(i) > 1:
        dupes.append(i)
    return dupes

if __name__ == "__main__":
assert list(check_duplicates([1, 2, 3, 4, 5])) == [],

Your Result:[]
Right Result:[]

import collections
dupes = []

def check_duplicates(data: list) -> list:

    for i in data:
        if data.count(i) > 1:
        dupes.append(i)
    return dupes

if __name__ == "__main__":
assert list(check_duplicates([1, 2, 3, 4, 5])) == [],

Your result:[1,3,1,3]
Right result:[]

Изначально у меня был массив вне функциии не смог вернуть пустой массив и задавался вопросом

1 Ответ

0 голосов
/ 28 декабря 2018

Хорошо, во-первых, исходный код ведет себя корректно в соответствии с тем, как он написан (но не так, как вы хотели), и перестанет давать пустые массивы, как только вы запустите его для списка, который создает непустой массив.Осталось только понять, почему он вел себя так, как и он.

Пояснение

Во-первых, списки - это изменяемые типы данных.

a = [1,2] #create a list object and bind it to the name a
b = a #both b and a are now referring to the same list object
a.append(3) #the list object a was referring to has been changed inplace, or mutated.
#notice that coincidentally b was referring to this same object
print(a) #Prints: [1,2,3]
print(b) #Prints: [1,2,3]

Это означает, что если вы используете метод списка для внесения изменений, например .append, он изменит объект списка на месте и все имена (например, a или * 1012).*) ссылка на него отразит изменение.

Во-вторых, Ваш оригинальный код с некоторыми комментариями

dupes = [] #create an empty list, and have the name dupes refer to the list object

def check_duplicates(data: list) -> list:


    for i in data:
        if data.count(i) > 1:
            dupes.append(i) #mutate the list object that dupes was referring to.
    return dupes #return the list object dupes was referring to.

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

dupes = []

def check_duplicates(data: list) -> list:


    for i in data:
        if data.count(i) > 1:
            dupes.append(i)
    return dupes

check_duplicates([1])
print(dupes) #[]
check_duplicates([2])
print(dupes) #[]
check_duplicates([1, 1])
print(dupes) #[1, 1]
check_duplicates([2])
print(dupes) #[1, 1] !!!! The dupes list continues to refer to the object, and any further append calls just add to it
check_duplicates([99, 99, 100, 100])
print(dupes) #[1, 1, 99, 99, 100, 100]
check_duplicates([2])
print(dupes) #[1, 1, 99, 99, 100, 100]

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...