Как выполнить цикл, пока все строки не будут прочитаны из файла? - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь настроить систему оценок, в которой мне нужно ввести все оценки из текстового файла в «массив записей».

Я довольно новичок в Python и надеюсь на простое решение.

В моей программе массив записей технически классифицируется как список namedtuples.

В настоящее время у меня есть:

Player = namedtuple("Player", ["name", "result", "difficulty", "score"])

Playerlist = []
while str(f.readline) != '':
    player = Player(
        f.readline(),
        f.readline(),
        f.readline(),
        f.readline())
    Playerlist.append(player)

Я пытался print(Playerlist[0]), но ничего не появляется.

Я также попытался print(Playerlist[0]) без какого-либо цикла и получил ожидаемый результат, хотя я не буду хранить все данные из текстового файла в моей программе.

Пример того, что находится в текстовом файле (scores.txt):

George
lost
H
18
Holly
lost
H
28
Marcus
won
H
30

EDIT: Я попробовал:

with open("scores.txt", "r") as f:
    for line in f:
        player = Player(
            f.readline(),
            f.readline(),
            f.readline(),
            f.readline())
        Playerlist.append(player)

Однако все содержимое получилось перепутанным:

Player(name='H\n', result='28\n', difficulty='Marcus\n', score='won\n')

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

Есть несколько проблем как с этим кодом, так и с этим подходом.Есть много форматов файлов, которые полезны для такого рода вещей;одна очень популярная, которая имеет встроенную поддержку 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)
0 голосов
/ 17 апреля 2019

Поскольку вы используете while str(f.readline) != '':, он читает первую строку. Поэтому первая строка (и, соответственно, все строки между записями) должна иметь пустую строку. Также readline в вашем while отсутствует парантез (). Кроме этого код работает в Python 3. Вы можете использовать with, чтобы открыть файл:

with open('test.txt', 'r') as f:
    while True:
        player = Player(f.readline(), f.readline(), f.readline(), f.readline())
        if "" in player:
            break;
        Playerlist.append(player)

for i in range(len(Playerlist)):
    print (Playerlist[i])

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

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