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?

Postby JanW » Wed Feb 20, 2013 2:51 pm

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=PLAYERSTATS
pointPool=30
choice = '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?

Postby Yoriz » Wed Feb 20, 2013 3:10 pm

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.
Reason: corrected the link
New Users, Read This
Join the #python-forum IRC channel on irc.freenode.net!
Image
User avatar
Yoriz
 
Posts: 1178
Joined: Fri Feb 08, 2013 1:35 am
Location: UK

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

Postby ichabod801 » Wed Feb 20, 2013 3:13 pm

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]
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 103
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

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

Postby JanW » Wed Feb 20, 2013 6:47 pm

Thanks for the quick reply.

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?

Postby micseydel » Wed Feb 20, 2013 6:51 pm

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.
Join the #python-forum IRC channel on irc.freenode.net!

Please do not PM members regarding questions which are meant to be discussed publicly. The point of the forum is so that others can benefit from it. We don't want to help you over PMs or emails.
User avatar
micseydel
 
Posts: 1507
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

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

Postby ichabod801 » Wed Feb 20, 2013 7:16 pm

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. :oops: 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.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 103
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

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

Postby micseydel » Wed Feb 20, 2013 9:23 pm

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.
Join the #python-forum IRC channel on irc.freenode.net!

Please do not PM members regarding questions which are meant to be discussed publicly. The point of the forum is so that others can benefit from it. We don't want to help you over PMs or emails.
User avatar
micseydel
 
Posts: 1507
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

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

Postby JanW » Thu Feb 21, 2013 12:07 pm

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?

Postby Mekire » Thu Feb 21, 2013 12:22 pm

PEP 8 is the recommended style guide for Python.
Here's a link: PEP 8

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
User avatar
Mekire
 
Posts: 1143
Joined: Thu Feb 07, 2013 11:33 pm
Location: Asakusa, Japan


Return to General Coding Help

Who is online

Users browsing this forum: No registered users and 4 guests

cron