Почему этот фрагмент списка необходим в этом понимании списка? - PullRequest
3 голосов
/ 21 сентября 2019

У меня есть вложенный список, и я хочу создать функцию для преобразования времени (с определенным форматом «XX: XX») в строку «время».Мне любопытно, почему мой первый пример работает, но не мой второй.Почему я должен клонировать каждый столбец, чтобы сохранить результаты списка?Списки изменчивы, поэтому я не могу просто сохранить результат строки на месте?

Не работает

def timeConvert2(schedule):
    for eachClass in schedule:
        eachClass = ["time" if x[2] == ':' else x for x in eachClass]
        return schedule

timeConvert([["abc", "09:09", "10:10"], ["def", "11:11", "12:12"]])

=> [["abc", "09:09", "10:10"], ["def", "11:11", "12:12"]]

Работает

def timeConvert1(schedule):
    for eachClass in schedule:
        eachClass[:] = ["time" if x[2] == ':' else x for x in eachClass]
        return schedule

timeConvert([["abc", "09:09", "10:10"], ["def", "11:11", "12:12"]])

=> [["abc", "time", "time"], ["def", "time", "time"]]

Iжду первого примера, который я привел, но первоначальный список не меняется ...

Ответы [ 3 ]

3 голосов
/ 21 сентября 2019

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

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

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

1 голос
/ 21 сентября 2019

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

def timeConvert2(schedule):
    for eachClass in schedule:
        print("ID before: {}".format(id(eachClass)))
        eachClass = ["time" if x[2] == ':' else x for x in eachClass]
        print("ID after: {}".format(id(eachClass)))
        return schedule

timeConvert2([["abc", "09:09", "10:10"], ["def", "11:11", "12:12"]])

ВЫХОД

ID before: 139823659735560
ID after: 139823659759816
[['abc', '09:09', '10:10'], ['def', '11:11', '12:12']]

Вы можете видеть, что ID из eachClass изменилсядо и после присвоения, что по существу означает, что вы создали новый объект.

def timeConvert1(schedule):
    for eachClass in schedule:
        print("ID before: {}".format(id(eachClass)))
        eachClass[:] = ["time" if x[2] == ':' else x for x in eachClass]
        print("ID after: {}".format(id(eachClass)))
        return schedule

timeConvert1([["abc", "09:09", "10:10"], ["def", "11:11", "12:12"]])

ВЫХОД

ID before: 139823659594440
ID after: 139823659594440
[['abc', 'time', 'time'], ['def', '11:11', '12:12']]

Вы можете видеть, что ID из eachClass не изменился до и после назначения, что по сути означает, что вы работаете с одним и тем же объектом.

Надеюсь, это поможет!

1 голос
/ 21 сентября 2019

Разница в следующем:

  • eachClass = X создает локальную переменную eachClass и присваивает ей X
  • eachClass[:] = X нарезает элемент исходного вложенного списка schedule, а назначает содержимое X этому срезу
list_a = [1,2,3]

for a in list_a:
    a = 5
    print(list_a)
>> [1,2,3]
>> [1,2,3]
>> [1,2,3]
list_a[0:2] = [5,5]
print(list_a)
>> [5,5,3]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...