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')
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)
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.