## Beginner: How to make a copy from a list?

This is the place for queries that don't fit in any of the other categories.

### Beginner: How to make a copy from a list?

I just started out programming and as an exercise I am writing a text based program which let you distribute 30 points from a pool to 4 attributes.
This exercise helps me to understand lists.

Scope of project:
The program lets the player distribute 30 points over 4 attributes.
The player cannot distribute more than 30 points and the player should be able to move distributed points back into the pool
Further more the player starts out with 5 points per attribute. You should not be able to remove more points than what you started with.
I have everything in here but there is one thing wrong with the programm (from a functional point of view). If I start over again with the new PLAYERSTATS the programm stil uses the starting attribute points of 5. Because of this line of code:

Code: Select all
`                if playerStats[attribute][1] - remove >= 5:                    playerStats[attribute][1]=playerStats[attribute][1]-remove                    pointPool=pointPool+remove `

So I want to make a copy of the PLAYERSTATS and use the copy to alter the values. And also use the original to compare the copy with to see if i don't remove points below the starting condition. But when I alter something in the copy of PLAYERSTATS automaticly PLAYERSTATS itself is altered.
If this al makes sense, my question is:'Can you make a copy of a list'?
And further remarks on the code are also welcome.

The whole code:
Code: Select all
`PLAYERSTATS=[['Health   ',5],['Strength ',5],['Wisdom   ',5],['Dexterity',5]]playerStats=PLAYERSTATSpointPool=30choice = 'start'while choice !='0':    print("""        Playerstats        0 - Exit        1 - Display stats        2 - Add points to attribute        3 - Remove points from attribute       """)    print('\n\t\tPoints to spend:', pointPool)    print('\n\t\tOriginal Strength:', PLAYERSTATS[1][1])    choice=input('choice:')        if choice == '0':        PLAYERSTATS=PLayerStats        print('Good bye.')    elif choice == '1':                             #Display Stats        print('\n\t Attributes:\t Points:')        for entry in playerStats:            (attribute, points)= entry            print('\t',attribute,'\t',points)        input()    elif choice == '2':                             #Add points from pool to attribute        print("""        Attributes - Adding points        0 - Health        1 - Strength        2 - Wisdom        3 - Dexterity        4 - Exit        """)        attribute=int(input('Which attribute:'))    #Choose Attribute to add to        while attribute != 4:            if  attribute in range(4):                print('How many points do you want to add to', playerStats[attribute][0])                add=int(input('Points:'))                if add <= pointPool:                    playerStats[attribute][1]=playerStats[attribute][1]+add                    pointPool=pointPool-add                    break                else:                    print('You do not have enough points.')                    input()            break        if attribute == 4:            input()    elif choice == '3':                             #Remove point from attribute to pool        print("""        Attributes - Removing points        0 - Health        1 - Strength        2 - Wisdom        3 - Dexterity        4 - Exit        """)        attribute=int(input('Which attribute:'))    #Choose Attribute to remove from        while attribute !=4:            if  attribute in range(4):                print('How many points do you want to remove from', playerStats[attribute][0])                remove=int(input('Points:'))                if playerStats[attribute][1] - remove >= 5:                    playerStats[attribute][1]=playerStats[attribute][1]-remove                    pointPool=pointPool+remove                                break                else:                    print('You do not have enough points.')                    input()            break                if attribute == 4:            input()`
JanW

Posts: 7
Joined: Sat Feb 16, 2013 8:35 pm

### Re: Beginner: How to make a copy from a list?

Yes you can make a copy of a list have a look at http://docs.python.org/2/library/copy.html a list with list will need deepcopy
Last edited by stranac on Wed Feb 20, 2013 6:58 pm, edited 1 time in total.
Due to the reasons discussed here we will be moving to python-forum.io/ on October 1 2016
This forum will be locked down and no one will be able to post/edit/create threads, etc. here from thereafter. Please create an account at the new site to continue discussion.

Yoriz

Posts: 1672
Joined: Fri Feb 08, 2013 1:35 am
Location: UK

### Re: Beginner: How to make a copy from a list?

Take a slice of the whole list:

Code: Select all
`copy_of_list = original_list[:]`

Note, that's what's called a shallow copy. It should work for you because you appear to have a list of integers. If you have mutable objects in the list you will need to use a list comprehesion to make new copies of each one. Like if you had a list of lists of integers:

Code: Select all
`copy_of_list = [sub_list[:] for sublist in original_list]`
Due to the reasons discussed here we will be moving to python-forum.io on October 1st, 2016.
This forum will be locked down and no one will be able to post/edit/create threads, etc. here from thereafter. Please create an account at the new site to continue discussion.
ichabod801

Posts: 688
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

### Re: Beginner: How to make a copy from a list?

I read the page on the link provided a couple of times but i can´t figure out what to do. If i want a new variable named 'newPlayStats' where do I use the 'method' .copy and what goes between the parentheses?

Code: Select all
`PLAYERSTATS=[['Health   ',5],['Strength ',5],['Wisdom   ',5],['Dexterity',5]]newPlayStats=PLAYERSTATS.copy()`

Further more i believe the list i want to copy contains lists within a list and also not only integers. So a simple copy will not do, right?
JanW

Posts: 7
Joined: Sat Feb 16, 2013 8:35 pm

### Re: Beginner: How to make a copy from a list?

Code: Select all
`new_player_stats = copy.deepcopy(PLAYERSTATS)`

assuming you've imported copy.

Once you're comfortable with this code and you have a bit of experience, I recommend learning "object-oriented programming". It's so fantastic for cases like this. It is an advanced topic in programming though, and many people have a hard time wrapping their minds around it.
Due to the reasons discussed here we will be moving to python-forum.io on October 1, 2016.

This forum will be locked down and no one will be able to post/edit/create threads, etc. here from thereafter. Please create an account at the new site to continue discussion.

micseydel

Posts: 3000
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

### Re: Beginner: How to make a copy from a list?

JanW wrote:Further more i believe the list i want to copy contains lists within a list and also not only integers. So a simple copy will not do, right?

Sorry, didn't look at your code too closely. Anyway, looking at your code it appears player_stats is a list of lists, each sub-list having a string and an integer. Lists are mutable, strings and ints are immutable. So my second example would work best for you. That is:

Code: Select all
`playerStats = [stat[:] for stat in PLAYERSTATS]`

If you don't understand that second part, it's called a list comprehension. It's a short way of writing a for loop that produces a list. It is equivalent to:

Code: Select all
`playerStats = []for stat in PLAYERSTATS:   playerStats.append(stat[:])`

BTW, your variable names have problems. It's generally good to stick to one style for variable names. Some of yours are in camelCase, and others are in ALLCAPS. This is especially confusing because playerStats and PLAYERSTATS are identical except for capitalization. It makes your code confusing, as it is not clear at each point which player stats you are talking about. It trips you up under if choice == '0' where you have PlayerStats, which is neither of them. I would call one startingStats, and the other workingStats, to help clarify which is which and what their purpose is.
Due to the reasons discussed here we will be moving to python-forum.io on October 1st, 2016.
This forum will be locked down and no one will be able to post/edit/create threads, etc. here from thereafter. Please create an account at the new site to continue discussion.
ichabod801

Posts: 688
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

### Re: Beginner: How to make a copy from a list?

I would recommend deepcopy over the list comprehension, both as a recommendation to someone who may not know about comprehensions and slicing (or why it works, and when it wouldn't work) and as a general recommendation, because if I were reading someone else's code, "deepcopy" makes sense instantly whereas reading the list comprehension, I can figure it out after some thinking, but then I'm not sure unless I look at the data if it's a true deep copy or just a less shallow shallow copy.

As for variable name conventions, constants as all case is something I use myself, and it looks like the OP is trying to do that here. The variable being all caps means it shouldn't be modified, and that is the case here. camelCase for other variable is alright, although PEP 8 recommends underscore_separated variable names.

I would recommend though instead of having the global constant, putting it in a function, and just having the function return a fresh version of that, and then eventually OOP as a replacement entirely.
Due to the reasons discussed here we will be moving to python-forum.io on October 1, 2016.

This forum will be locked down and no one will be able to post/edit/create threads, etc. here from thereafter. Please create an account at the new site to continue discussion.

micseydel

Posts: 3000
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

### Re: Beginner: How to make a copy from a list?

Thanks guys. It is working. I havn't reached the chapters about functions and OOP so this will have to do for now.

Code: Select all
`PLAYERSTATS=[['Health   ',5],['Strength ',5],['Wisdom   ',5],['Dexterity',5]]newPlayerStats=copy.deepcopy(PLAYERSTATS)`

Code: Select all
`if newPlayerStats[attribute][1] - remove >= PLAYERSTATS[attribute][1]:`

Itried al different variations with copy.copy(X) but none of them worked.
But this was a big clue:
assuming you've imported copy.

BTW, your variable names have problems. It's generally good to stick to one style for variable names. Some of yours are in camelCase, and others are in ALLCAPS. This is especially confusing because playerStats and PLAYERSTATS are identical except for capitalization. It makes your code confusing, as it is not clear at each point which player stats you are talking about. It trips you up under if choice == '0' where you have PlayerStats, which is neither of them. I would call one startingStats, and the other workingStats, to help clarify which is which and what their purpose is.

I am learning from a book and a couple of webpages. And here it is said that if you have a constant variable that you don't want to change you write it in all caps to remind you that it is a constant.

As for variable name conventions, constants as all case is something I use myself, and it looks like the OP is trying to do that here. The variable being all caps means it shouldn't be modified, and that is the case here. camelCase for other variable is alright, although PEP 8 recommends underscore_separated variable names.

I would recommend though instead of having the global constant, putting it in a function, and just having the function return a fresh version of that, and then eventually OOP as a replacement entirely.

I chose to program in 'camelCase' because I find it harder to read compared to 'underscore_separated'. So when i familiarise myself with 'camelCase' I can read other peoples code done in 'camelCase' more easily.

What is PEP8 exactly?
JanW

Posts: 7
Joined: Sat Feb 16, 2013 8:35 pm

### Re: Beginner: How to make a copy from a list?

PEP 8 is the recommended style guide for Python.

Also for your code; that list really looks like it would be happier as a dictionary:
Code: Select all
`PLAYERSTATS = {'Health':5,'Strength':5,'Wisdom':5,'Dexterity':5}`
Although, if that PLAYERSTATS name is really a constant, and all the minimum values are going to be 5 anyway, there is no need to keep track of them this way.

Just have:
Code: Select all
`MINSTAT=5`
and use it when trying to change any attribute. No need to keep track of four constants that are all 5.

-Mek
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1711
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona