Есть несколько проблем как с этим кодом, так и с этим подходом.Есть много форматов файлов, которые полезны для такого рода вещей;одна очень популярная, которая имеет встроенную поддержку Python: JSON .
import json
from pprint import pprint
old_players = [
{
'name': 'Bob',
'result': 'success?',
'difficulty': 'hard',
'score': 55,
},
{
'name': 'Tatsuki',
'result': 'embarrassment',
'difficulty': 'easy',
'score': -2,
},
]
with open('player-file.json', 'w') as outfile:
outfile.write(json.dumps(old_players))
with open('player-file.json', 'r') as infile:
new_players = json.loads(infile.read())
pprint(new_players)
# [{'difficulty': 'hard', 'name': 'Bob', 'result': 'success?', 'score': 55},
# {'difficulty': 'easy', 'name': 'Tatsuki', 'result': 'embarrassment', 'score': -2}]
namedtuple
- это не то, что я часто использую.Использование его с JSON может быть немного проблематичным, и, хотя есть обходные пути , возможно, было бы лучше использовать класс Player
с простым настраиваемым сериализатором, подкласс класса, созданного с помощью namedtuple
который определяет метод, возвращающий либо JSON, либо форматируемый JSON dict (довольно запутанный), либо пишет отдельную функцию, которая явно переводит ваши namedtuple
объекты в JSON.
Что касается чтения вашего существующего формата:
from pprint import pprint
from collections import namedtuple
Player = namedtuple("Player", ["name", "result", "difficulty", "score"])
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
with open('/tmp/players.old', 'r') as infile:
lines = [l.strip() for l in infile.readlines()]
for player_values in chunks(lines, 4):
pprint(Player(*player_values))
# Player(name='George', result='lost', difficulty='H', score='18')
# Player(name='Holly', result='lost', difficulty='H', score='28')
# Player(name='Marcus', result='won', difficulty='H', score='30')
Функция chunks
взята из этого ответа .Это зависит от того, знаете ли вы количество распаковываемых значений для каждого игрока, которое не может быть изменено для этого формата.
Когда здесь читается lines
, используется понимание списка для удаления новой строки с конца каждого значения.
Наконец, кортеж Player
создается с помощью player_values
, список генерируется с помощью chunks
и расширяется с использованием *
.Это означает, что вместо передачи списка player_values
в функцию Player.__init__(...)
отдельные значения будут отправлены как *args
.Таким образом, вместо Player([name, result, difficulty, score])
вызов метода становится Player(name, result, difficulty, score)
.
. Хотя это технически возвращает значения, имейте в виду, что score
, назначенный здесь, является строкой, а не числовым значением.Если вы хотите, чтобы это было приведено, например, к int
, вам нужно выписать полное описание:
# ...
for player_values in chunks(lines, 4):
pprint(Player(
player_values[0],
player_values[1],
player_values[2],
int(player_values[3]),
))
# Player(name='George', result='lost', difficulty='H', score=18)
# Player(name='Holly', result='lost', difficulty='H', score=28)
# Player(name='Marcus', result='won', difficulty='H', score=30)