Python добавление новых строк в список дублирует только последнее [дублировать]

На этот вопрос уже есть ответ здесь:

Я пытаюсь добавить новые строки в список, но кажется, что только последняя строка реплицируется в список столько раз, сколько создается новая строка.
Поэтому я сделал небольшой тестовый сценарий, который демонстрирует мою проблему.
Что я хочу, чтобы добавить столько строк в исходный список, как есть ночи в строке и добавить день в исходную дату, если есть 7 ночей я хочу иметь 7 строк только с другой датой. Из этого я создаю текстовый файл, чтобы отправить мне по почте, своего рода ежедневный отчет, поэтому я знаю, что ожидать в этот день в нашем B&B и включить или выключить водогрейные котлы

Это мой тестовый скрипт на Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from datetime import datetime, timedelta

NIGHTS = 12  # number of nights a guest stays @ our B&B
CHECKIN = 0  # date the guest checks in
aList = []

""" 
contents test agenda.dat
   check in                           nights
     V                                 V
"2016-10-27,1,*,K4,A1,*,D4,*,PD,PF,0,*,7,TEST4,remark"
"2016-10-28,1,*,K4,A1,*,D4,*,PD,PF,0,*,1,TEST1,remark"
"2016-10-29,1,*,K4,A1,*,D4,*,PD,PF,0,*,1,TEST2,remark"
"2016-10-30,1,*,K4,A1,*,D4,*,PD,PF,0,*,2,TEST3,remark"

copy past this into agenda.dat and you have your file

"""

#
# --------- convert date --------- #
def date(cDate=None, format='%Y-%m-%d'):
    if not cDate:
        dDate = datetime.today().date()
    else:
        dDate = datetime.strptime(cDate, '%Y-%m-%d')

    return dDate

#
# --------- get contents agenda -------- #
#
def read_agenda():

    aBooking=[]

    with open("agenda.dat", "r") as f:
        next(f)  # skip header line

        for line in f:
            line = line.strip()
            aBooking.append(line.split(","))

    return aBooking


aList = read_agenda()

# checking out contents of aList
######
for x in aList:
    print x

print "============="
# it checks out

# thought using an empty list would solve the problem, not
bList = []

newline = []  # just declaring everything would help?
n = 0         # not

#######
for x in aList:
    n = int(float(x[NIGHTS]))
    newline = x

    # the first agenda-data line contains '7' so n = 7

    while n > 1:
        cDatum = date(newline[CHECKIN]).date() + timedelta(days=1)
        newline[CHECKIN] = "{:%Y-%m-%d}".format(cDatum)
        newline[NIGHTS] = str(1)

        # just to check if the conversion went ok, yes
        print newline
        # output:
        # ['2016-10-28', '1', '*', 'K4', 'A1', '*', 'D4', '*', 'PD', 
        # 'PF',  '0', '*', '1', 'TEST1', 'remark']

        # and now it happens adding a line to this aray ends in 
        # replicating n lines with the same contents
        # this should not be, a new line should contain a new date
        bList.append(newline)
        n -=1


################
print "==== bList ========="
for y in bList:
    print y
# this prints the same line 7 times!

print "=== aList =========="
for x in aList:
    print x
# and yes the original data is still intact except for the 7 this turned 
# into 1 as desired

вопрос:
что я делаю неправильно здесь
I should get 7 lines with incrementing dates for the first record
и 2 строки для последнего.

1 ответ

  1. Ваш внутренний цикл while n > 1:продолжает изменять один и тот же newlineобъект и присоединять его к bListнему . Таким образом , вы не получаете 7 различных newlineобъектовbList, вы получаете 7 ссылок на один и тот же newlineобъект.

    Вы можете исправить эту проблему, избавившись от этого

    newline = x
    

    линия перед while n > 1:началом цикла и изменение его на

    while n > 1:
        newline = x[:]
    

    Это создаст новый newlineобъект (скопированный изx) на каждой итерации цикла.

    Это решение будет работать, если xесть список строк. Однако если xэто действительно список списков, то вам, возможно, придется создать копии этих внутренних списков.