# Printing a score sheet for baseball batters

I've been learning Python 2.7 for about a week now and have written a quick program to ask for names of batters and printing a score sheet. I have then added the names to a list which I will use more in other future functions.

I have a few questions:

1. I feel like there is too much repetition in my code, such as the prompting for each batter and all the printing. I am trying to figure out how I could use a loop to do these for me. Since I know I need 11 batters a for loop would be best but I need to make a new variable each time, how can I do this?

2. I have been reading around about the use of global. I can't seem to get a definite answer but is this the correct use if I want to use a variable from one function in multiple others?

def Input_Players():

global First, Second, Third, Fourth, Fith, Sixth, Seventh, Eigth, Ninth, Tenth, Eleventh

First = [raw_input("Name of 1st Batsman > ")]
Second = [raw_input("Name of 2nd Batsman > ")]
Third = [raw_input("Name of 3rd Batsman > ")]
Fourth = [raw_input("Name of 4th Batsman > ")]
Fith = [raw_input("Name of 5th Batsman > ")]
Sixth = [raw_input("Name of 6th Batsman > ")]
Seventh = [raw_input("Name of 7th Batsman > ")]
Eigth = [raw_input("Name of 8th Batsman > ")]
Ninth = [raw_input("Name of 9th Batsman > ")]
Tenth = [raw_input("Name of 10th Batsman > ")]
Eleventh = [raw_input("Name of 11th Batsman > ")]

def Print_Score_Sheet():
total_chars = 56

Batsman = First + Second + Third + Fourth + Fith + Sixth + Seventh + Eigth + Ninth + Tenth + Eleventh

print "1." + Batsman[0] + "." * (total_chars - len(Batsman[0]) + 2)
print "2." + Batsman[1] + "." * (total_chars - len(Batsman[1]) + 2)
print "3." + Batsman[2] + "." * (total_chars - len(Batsman[2]) + 2)
print "4." + Batsman[3] + "." * (total_chars - len(Batsman[3]) + 2)
print "5." + Batsman[4] + "." * (total_chars - len(Batsman[4]) + 2)
print "6." + Batsman[5] + "." * (total_chars - len(Batsman[5]) + 2)
print "7." + Batsman[6] + "." * (total_chars - len(Batsman[6]) + 2)
print "8." + Batsman[7] + "." * (total_chars - len(Batsman[7]) + 2)
print "9." + Batsman[8] + "." * (total_chars - len(Batsman[8]) + 2)
print "10." + Batsman[9] + "." * (total_chars - len(Batsman[9]) + 1)
print "11." + Batsman[10] + "." * (total_chars - len(Batsman[10]) + 1)

Input_Players()
Print_Score_Sheet()


I would structure the code like this:

def input_players(total=11):
players = []

for index in range(total):
player = raw_input('Name of Batsman {} > '.format(index + 1))
players.append(player)

return players

def print_score_sheet(batsmen, total_chars=56):
for index, batsman in enumerate(batsmen, 1):
print '{}. {} '.format(index, batsman).ljust(total_chars, fillchar='.')

if __name__ == '__main__':
players = input_players(11)
print_score_sheet(players)


Some tips:

• If you use a set of variables like Player1, Player2, PlayerN, you should be using a list to store them.
• Your functions should do what they say. input_players() should return a list of players, nothing more, nothing less.
• Get into the habit of including the if __name__ == '__main__': block. The stuff inside of the block is executed only if you run the Python script directly, which is good if you have multiple modules.
• Minor improvement, you could use enumerate(batsmen, 1) which would avoid having to use index + 1 – Greg Hewgill Jun 20 '12 at 21:07
• Thanks, I didn't know there was a better way of doing the i + 1 thing. – Blender Jun 20 '12 at 21:08
• Another tip I'd add is that the OP should look at PEP 8, purely to get a feel for Python conventions with regard to naming. His current use of initial caps will confuse experienced devs expecting classes. – JPvdMerwe Jun 21 '12 at 0:13
• Thanks for the help. Yes it looks like I need to read up a bit more on manipulating lists, that .append looks like exactly what I need. – Behzad Jun 21 '12 at 7:06

If you find yourself using serialized variable names (player1, player2, etc) it is a pretty sure sign you should be using a list or dictionary instead.

Global is useful if, in a function, you are using a variable from a higher scope and need to store changes back to it. In most cases, it is better to return the result from the function instead of trying to 'smuggle it out' this way.

def get_player(n):
return raw_input('Name of Batsman {} > '.format(n)).strip()

def get_players(num_players=11):
return [get_player(i) for i in xrange(1,num_players+1)]

def score_sheet(players, width=56, fillchar='.'):
lines = ('{}. {} '.format(*x).ljust(width, fillchar) for x in enumerate(players, 1))
return '\n'.join(lines)

def main():
print score_sheet(get_players())

if __name__=="__main__":
main()

• It is in functions, just not indented. – Lev Levitsky Jun 20 '12 at 20:49
• Writing your own rightfill is redundant: you could utilise something similar to format('test', '.<56') – Jon Clements Jun 20 '12 at 20:58
• @Jon Clements: thank you, I was not aware of that. Updated to incorporate it. – Hugh Bothwell Jun 20 '12 at 21:06
• @Jon Clements: on second thought, I prefer Blender's str.ljust() - but still, it was a good suggestion. – Hugh Bothwell Jun 20 '12 at 21:20

Wherever anyone uses global, that is a strong indication that a class should be used instead.

• Why a class rather than just passing around function return values? In particular in this case? – weronika Jun 23 '12 at 23:05
• @weronika For starters, because there are numerical and non-numerical relationships between the values. By factoring it into a single kind of value, that relationship can be made explicit. In this case, it would be enough to simply create a size-eleven tuple, and pass that as a single value. – Marcin Jun 24 '12 at 4:55