I'm trying to set up a score system where I need to input all the scores from a text file into an 'array of records'.
I'm fairly new to Python
and hope for a simple solution.
In my program, the array of records would technically class as a list of namedtuples
.
Currently I have:
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)
I tried to print(Playerlist[0])
, but nothing shows up.
I have also tried to print(Playerlist[0])
without any loop and got the expected result, though I won't have stored all the data from the text file into my program.
An example of what is in the text file (scores.txt
):
George
lost
H
18
Holly
lost
H
28
Marcus
won
H
30
EDIT: I tried:
with open("scores.txt", "r") as f:
for line in f:
player = Player(
f.readline(),
f.readline(),
f.readline(),
f.readline())
Playerlist.append(player)
However all of the contents came out mixed up:
Player(name='H\n', result='28\n', difficulty='Marcus\n', score='won\n')
答案 0 :(得分:0)
There are several problems with both this code and this approach. There are many file formats that are useful for this kind of thing; one very popular one that has built-in Python support is 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
isn't something I see used often. Using it with JSON can be a bit wonky, and while there are workarounds, it might be a better idea to either use a Player
class with a simple custom serializer, subclass a class generated by namedtuple
that defines a method to return either JSON or a JSON-formattable dict (pretty convoluted), or write a separate function that explicitly translates your namedtuple
objects into JSON.
Regarding reading your existing format:
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')
The chunks
function comes from this answer. It depends on you knowing the number of values you're unpacking per player, which can't change for this format.
When lines
is read here, a list comprehension is used to strip the newline from the end of each value.
Finally, the Player
tuple is instantiated with player_values
, a list generated by chunks
and expanded using *
. This means, instead of passing the list player_values
to the function Player.__init__(...)
, the individual values will be sent as *args
. So effectively, instead of Player([name, result, difficulty, score])
, the method call becomes Player(name, result, difficulty, score)
.
While this technically retrieves the values, note that the score
that's assigned here is a string, not a numeric value. If you want that to be cast to an int
, for example, you'd need to write out the full instantiation:
# ...
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)
答案 1 :(得分:-1)
Since you are using while str(f.readline) != '':
it reads first line. Therefore, first line(and by extension all lines between records) must have blank line. Also readline
in your while
is missing paranthesis()
. Other than that the code is working in python 3. You can use with
to open file:
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])
It automatically closes files and handles details for you. However, using json or other formats in a better option.