Я пишу сценарий для отправки статистики из текстового файла в Markdown. Файл содержит названия книг и даты. Каждая дата относится к следующим заголовкам, пока не появится новая дата. Вот пример:Нечетное поведение петли в Python
#### 8/23/05
Defining the World (Hitchings)
#### 8/26/05
Lost Japan
#### 9/5/05
The Kite Runner
*The Dark Valley (Brendon)*
#### 9/9/05
Active Liberty
Я перебрать строки в файле с for
цикла и рассмотрим каждую строку, чтобы увидеть, если это дата. Если это дата, я устанавливаю переменную this_date
. Если это заголовок, я делаю его в dict с текущим значением this_date
.
Существует два исключения: файл начинается с заголовков, а не с даты, поэтому я устанавливаю начальное значение для this_date
перед циклом for. И на полпути через файл есть область, где даты были потеряны, и я установил конкретную дату для этих названий.
Но в результирующем списке dicts все заголовки даны этой дате до начала области потерянных данных. После этого в остальной части заголовков указывается дата, которая появляется последним в файле. Самое смутное: когда я печатаю содержимое this_date
непосредственно перед добавлением нового dict, он содержит правильное значение для каждого цикла.
Я ожидаю, что this_date
будет виден на всех уровнях цикла. Я знаю, что мне нужно разбить это на функции, и передача результатов явно между функциями, вероятно, устранит проблему, но я хотел бы знать, почему этот подход не сработал. Большое спасибо.
result = []
# regex patterns
ddp = re.compile('\d+') # extract digits
mp = re.compile('^#+\s*\d+') # captures hashes and spaces
dp = re.compile('/\d+/') # captures slashes
yp = re.compile('\d+$')
sp = re.compile('^\*')
# initialize
this_date = {
'month': 4,
'day': 30,
'year': 2005
}
# print('this_date initialized')
for line in text:
if line == '':
pass
else:
if '#' in line: # markdown header format - line is a new date
if 'Reconstructing lost data' in line: # handle exception
# titles after this line are given 12/31/14 (the last date in the file) instead of 8/31/10
# all prior dates are overwritten with 8/31/10
# but the intent is that titles after this line appears have date 8/31/10, until the next date
this_date = {
'month': 8,
'day': 31,
'year': 2010
}
# print('set this_date to handle exception')
else: # get the date from the header
month = ddp.search(mp.search(line).group()) # digits only
day = ddp.search(dp.search(line).group()) # digits only
year = yp.search(line)
if month and day and year:
# print('setting this_date within header parse')
this_date['month'] = int(month.group())
this_date['day'] = int(day.group())
this_date['year'] = (int(year.group()) + 2000)
else:
pass
else: # line is a title
x = {
'date': this_date,
'read': False
}
if sp.match(line): # starts with asterisk - has been read
x['read'] = True
x['title'] = line[1:-3] # trim trailing asterisk and spaces
else:
x['title'] = line
# this_date is correct when printed here
# print('this_date is ' + str(this_date['month']) + '/' + str(this_date['day']) + '/' + str(this_date['year']))
result.append(x)
# x has correct date when printed here
# print(x)
# print("Done; found %d titles.") % len(result)
# elements of result have wrong dates (either 8/31/10 or 12/31/14, no other values) when printed here
# print(result[0::20])
Кроме того, создать новый Dict вместо модификации старой. Тогда нет необходимости копировать его сотни раз. –
@Rawing: OP упомянул, что они ожидают, что дата будет использоваться повторно в последующих итерациях. –
Оба подхода работали. Что такое компромисс между вставкой копии dict 'date': this_date.copy() и созданием нового dict 'date': { 'month': this_date ['month'], 'day': this_date [ 'day'], 'year': this_date ['year'] } – user2014160