Easy for some, tricky for some, can you give me a hand with a bit of Python code please

Hello people, a bit of Python help required.

It is a basic program, however I am a bit stuck.

I want to store basketball player information, and the things I want to store are Player name and Player height.

Also, I want to be able to iterate using loops through that list, so therefore I made a list of dictionaries to achieve that?I am not sure if everything is correct?

The code below


print("Basketball players ranker")

p_num = int(2)

player_info = [{

    "Name":[],

    "height":[]

}]

for i in range(p_num):

    print("please enter player name")

    player_name = input()

    print("please enter player height")

    player_height = int(input())

    

    player_info.append(["Name"].append(player_name))

    player_info.append(["height"].append(player_height))

        

counter = int(0)

print("so we got the folowing info")

for i in player_info:

    print(player_info[counter].get("Name"))

    print(player_info[counter].get("height"))

    counter +=1

The output example below


Basketball players ranker

please enter player name

pl1

please enter player hight

10

please enter player name

pl2

please enter player hight

20

so we got the folowing info

[]

[]

Traceback (most recent call last):

  File "d:\python\projects\python_learning\python-exirsizes\x3.py", line 22, in <module>

    print(player_info[counter].get("Name"))

AttributeError: 'NoneType' object has no attribute 'get'

PS D:\python\projects\python_learning\python-exirsizes>

I think from my code above you should understand what I am trying to achieve and if I am totally wrong please provide me the corrected code if you can.

Thanks very much for your help.

Hi @zen , let me go through each step where I think there’s some scope for improvement or correction. Others may add things which I miss.

p_num = int(2)

Coercing it to an integer is not strictly necessary in this context; it’s not wrong, but p_num = 2 would have sufficed and is more readable. Similarly, when you initialise counter later on.

player_info.append(["Name"].append(player_name))
player_info.append(["height"].append(player_height))

After getting both sets of inputs, did you try to print out player_info? (It’s good practice to make sure that you’re on the right track.) If you had done so, you’d have noticed that it contains

[{'Name': [], 'height': []}, None, None, None, None]

regardless of what you typed in.

That’s because you’re creating ["Name"].append(<something>) and ["height"].append(<something>), which are actually lists and not the dictionary keys you were expecting. When you append something to an “anonymous” list, i.e. a list that isn’t bound to a (variable) name, nothing (on None, to be precise) is returned. (Try it out in an interpreter.) And this None is then appended to you original list, player_info. This is the source of the error that you received. Even though your intention was not to add to the list, Nones were added and when the code tried to access a non-existent .get() method on a None object, it broke.

It should instead be:

# Get the first, and in this case the only, element of the list -- which is a dictionary
# Get the value associated with key "Name" in that dictionary -- which is another list
# Append the player's name to that list
player_info[0]["Name"].append(player_name)
player_info[0]["height"].append(player_height)

If you ask me, I’d ditch the list and make player_info a dictionary instead, unless you have plans of extending it. But for the moment, let’s stick with the list and see what can be done with the output:

for i in player_info:
    print(player_info[counter].get("Name"))
    print(player_info[counter].get("height"))
    counter +=1

One must keep in mind that when using a for loop to iterate over something like a list or a tuple, among other things, in Python, in each iteration you already get hold of an element in that list or tuple and that there is no need to keep track of a counter unless required to keep track of something else. But since player_info is a one-element list, there is no reason to loop over it at all. Let’s instead extract just the dictionary and loop through the names and heights:

player_dict = player_info[0]
for name, height in zip(player_dict["Name"], player_dict["height"])
    print(name, height, sep='\n', end='\n\n')

I have use the zip function to give us a single iterator that pairs up corresponding names and heights and use the formatting options in the print function to simplify the code. And notice that we can assign separate names for each item in a pair, triple, 4-tuple etc. (In this case name, height.) This is called unpacking.

Another way of doing the same thing, and, IMHO, the better way too:

player_dict = player_info[0]
for name, height in player_dict.items():
    print(name, height, sep='\n', end='\n\n')