I'm currently making my first project in Python - tic tac toe as i thought it would be a good place to start and I've finally hit a road block.
I've currently got the board setup as a list - Board = [1,2,3...,9] and to reset, Board's contents is deleted and re-entered by a separate list however it also adds the brackets.
Is there a way to grab the contents of a separate list without also grabbing the brackets?
if newGame == 'Y' or 'y':
del Board[:]
Board.append(startBoard)
print Board #for testing
else:
sys.exit('game over')
What I'm getting is looking like this:
[[1,2,3,4,5,6,7,8,9]]
Use extend.
Board.extend(startBoard)
Alternatively you can do:
Board = [el for el in startBoard]
and omit the del Board[:] althogether.
Alternatively you can use the copy module:
Board = copy.deepcopy(startBoard)
For me the best will be this though:
Board = [i+1 for i in xrange(9)]
Or the simpler:
Board = range(1, 10) # python 2
or
Board = list(range(1, 10)) # python 3
As zehnpaard suggested in the comments.
Also you can do what Erik Allik has proposed in his answer.
if you want to clear out and modify the contents of a list in-place (as opposed to creating a new fresh list and assigning it back to the variable that holds your old list):
board[:] = startBoard
which, if nothing that needs to see the latest board contents points to the old list, is functionally equivalent to:
board = startBoard
you can get an idea of what it means to modify something in-place vs create a fresh copy/instance if you play around a little bit with assigning the same contents to multiple variables without making copies in the process.
Also, note that since startBoard in your case is a constant, you want to make sure nothing ever modifies it, so the 2nd example is really a very bad idea. There's also however a 3rd:
board = startBoard[:]
which is actually by far the best of all three. What it does is make a copy of startBoard and assign it to the variable board without ever modifying the old list board was pointing to. Also, because you're using a copy of startBoard, you can be sure your start board is always the same in the future.
Note that these aspects arise only in programming languages or styles where mutable datatypes are used; in Functional Programming, almost nothing ever gets modified so you can completely become ignorant of worrying about causing accidental adverse side-effect by touching something someone else is relying on.
Furthermore: note that copying a list can be done in a multitude of ways in Python; from a high level point of view which I'm currently speaking out for there is little difference though, so copy.copy(startBoard) is the same as [x for x in startBoard) is the same as startBoard[:] etc.
See also the PEP8 which provides you with useful coding conventions.
Try this:
for x in startBoard:
Board.append(x)
Related
For some reason, I have a list that keeps getting modified despite being explicitly a deep copy. It appears to be unmodified as it goes through the loop, but it suddenly is modified once it exists? I must be missing something that pertains to Python's rules and logic, but I can't figure it out for the life of me.
def all_possible_states(self):
#creates many variations of a board from the available set of moves
to_return = [] #list of possible board states to return
#print(self.availible_moves)
list_to_copy = copy.deepcopy(self.availible_moves)
for item in self.availible_moves:
print('loop')
#append possible board state to list. set of availible moves for that board is one less. Done by removing item from that move list
to_return.append(board(self.player, copy.deepcopy(self.board.copy()), list_to_copy, self.plays, self.score, copy.deepcopy(item)))
#print(item)
print( self.avalible_moves) #shows the total set of moves. This is unmodified whenever it prints
print(list_to_copy)#deep copy of the original list. This is unmodified when it prints
print(to_return[len(to_return) - 1].availible_moves) #List of moves left availible for the board, this slowly shrinks for some reason each loop
print(self.availible_moves) #this is the original list, but it's not basically been cut all the way down for some reason
return to_return
Notice, the local variable list_to_copy is the deepcopy, not self.availible_moves. You are saving a deepcopy of self.availible_moves and it is being stored in the list_to_copy variable you defined. list_to_copy never changes as expected from a deepcopy. I'm not exactly sure what you are trying to do, but if you want, at the end you can reset self.availible_moves to be equal to list_to_copy and then it will be as if it never changed.
EDIT:
Actually, I think you have a spelling mistake, notice that you print(self.avalible_moves) and you are saying its not changing, when really what is changing is self.availible_moves. Notice the extra letter i in the first expression. This definitely is one of your problems.
No, this is not a duplicate.
I have the following classes:
-Board
-Player
When Player is instantiated, it creates a new board object for that player.
I have a function which switches the current and latent players:
from copy import deepcopy
switch_players(self):
temp_val = deepcopy(self.current_player)
# self.current_player = None
self.current_player = deepcopy(self.latent_player)
# self.latent_player = None
self.latent_player = deepcopy(temp_val)
temp_val = None
This works fine for the players' names when I call self.current_player.name, but when I use self.current_player.board.display, or write to it, it references the same board for both players.
I even added code to create a deepcopy() of the board to switch like this, but I'm still experiencing the same issue. Is this a fundamentally wrong way to do something like this? Or is this approach correct, and I should look elsewhere in my code? (I have another way of doing this, but I'm not understanding the theory behind why this current approach doesn't work.)
It works so, because name is string, board is class instance which will be copied, but it is one level deeper, so it will not be copied with deepcopy. Deepcopy is not meant recursively.
Sorry for confusing title name, I wasn't quite sure how to word it.
I have the code below:
eps = []
newdict = dictionary.items
for ep in range(minepisode, maxepisode + 1):
eps.append(str(ep))
for key in dictionary.keys():
if key not in eps:
newdict.pop(key)
However, when I try to run it, it returns with the error,
RuntimeError: dictionary changed size during iteration
despite the changes were being made to 'newdict' and not 'dictionary', which was the one I was iterating.
After messing around in shell I found that if I made 2 identical dictionary like this:
x = {'1':'something'}
newx = x
newx.pop('1')
Both the '1' key in x AND newx were removed. Why is this? And how should I fix the error in the original code?
Firstly dict in python is mutable data structure..
So, it works like this..
x = {'1':'something'}
So, here dict object x has been created...
newx = x
So, here you referred the same dict object to another variable called newx.
Ideally you didn't create a new object, you just referenced the same object to other variable..
You can see that similarity like this..
>>> id(x)
140222539383424
>>> id(newx)
140222539383424
Id's of both the objects are same...
You can also verify this by using object similarity check by using is
>>> newx is x
True
So, for obvious reasons it doesn't matter whether you are trying to change x or newx, you are changing the same referenced object.
If you want to change a dict while in loop, you should use copy.deepcopy(); it will allocate separate memory for both.
Example:
import copy
a = {'key':'value'}
b = copy.deepcody(a)
Hopefully it will help you. :)
Consider you have a list colours=['blue','green]. When you do something like palette=colours you make palette an alias to colours: they both refer to the same list located at the same memory address.
colours=['blue','green']
palette=colours
print id(colours)==id(palette) #True
print id(colours[0])==id(palette[0]) #True
There is a way to change it. Consider you define palette=list(colours). Now you created a new list that is located at another address in memory. But now both lists contain elements at the same adress: palette[0] and colours[0] are located at the same address.
colours=['blue','green']
palette=list(colours)
print id(colours)==id(palette) #False
print id(colours[0])==id(palette[0]) #True
Finally, you have deepcopy
from copy inport deepcopy
colours=['blue','green']
palette=deepcopy(colours)
print id(colours)==id(palette) #False
print id(colours[0])==id(palette[0]) #False
You have a dog, you're an extraordinary person and you call your dog flash on even days and turtle on odd ones. Today, March 28th, flash hurts their front right leg, would you be surprised if tomorrow you'll find that turtle too has a wounded front right leg?
Python is like that, you have objects that are permanent and names that you stick on them... some of these objects are immutable (e.g., strings) and when you think to modify one of them you're creating a new object instead, the old object still around, the old labeled by flash and the new by turtle --- others are mutable (e.g., dictionaries) so that a change can be directly applied to the object itself, that is still referred by all their names.
To me, immutable objects' behavior is most surprising but I understand I'm a minority... and as such I need preservation.
Disclaimer: no animal was actually hurt in the making of this post.
In the Tetris game in the PyGame book, they create a board using:
board = []
for i in range(BOARDWIDTH):
board.append([BLANK] * BOARDHEIGHT)
return board
While that's fine, a list of lists, I was thinking about how they usually represent that in Java and other languages, as an array with set index - for example, int board[][] = new int[8][8]; // create 64 integers (a 2d array example).
From what I understand, tuples are more similar to the array (vs List which is more like ArrayList or LinkedList of Java). They have set number of elements and can't be added to, and hold a set number of items.
Why would we not create a tuple of tuples for a board, for example
board = ( (BLANK,)*10 ,)*10
Do they use lists of lists for some optimization in Python's internal representation of the board, or just because they assume users know List more commonly than Tuple?
This has the added benefit of being functional and making immutable objects. If you want to make a board with a state in which you moved in tic tac toe for example, you could try something like:
tictac = ((0,0,0),)*3
vals = (tuple((tictac[r][c]) if r!=1 or c!=1 else 'x' for (r,row) in enumerate(tictac)) for c in range(3))
for i in vals: print i
to move a 1 to the center.
List comprehensions are quite flexible in Python and this is more functionally-correct.
The difference between list and tuple in python is that tuple is immutable. That's why you can't change the size of a tuple (since you can't change it at all).
So the reason one normally would chose a list in this case is that you normally want to change the contents of the game board.
The benefits of having a matrix of fixed size may be slim. One could of course argue that one might get some performance benefit, but AFAIK the built in types are anyway of dynamic size in the sense that the size is determined at runtime and each time you access the container. In this aspect the list and tuple does not differ, that is when you write board[3][4] python would first access board check if it's length is larger than 3 so it can deliver the [3] element, then that element happens to be a list/tuple which is then checked for it size so it's larger than 4 so it can deliver the [4] element.
One could also argue that it would be for safety reasons or that it's "good practice" to not allow the board to be resized, and I could agree on that. What one then would do to allow modification is to wrap it all in a class that doesn't allow for resizing. One should bear in mind however that python doesn't provide very hard protection of classes that prohibit you from fiddling with internals - rather python trusts the programmer to not doing ugly things instead of trying to forbid.
I am considering moving from Matlab to Python/numpy for data analysis and numerical simulations. I have used Matlab (and SML-NJ) for years, and am very comfortable in the functional environment without side effects (barring I/O), but am a little reluctant about the side effects in Python. Can people share their favorite gotchas regarding side effects, and if possible, how they got around them? As an example, I was a bit surprised when I tried the following code in Python:
lofls = [[]] * 4 #an accident waiting to happen!
lofls[0].append(7) #not what I was expecting...
print lofls #gives [[7], [7], [7], [7]]
#instead, I should have done this (I think)
lofls = [[] for x in range(4)]
lofls[0].append(7) #only appends to the first list
print lofls #gives [[7], [], [], []]
thanks in advance
Confusing references to the same (mutable) object with references to separate objects is indeed a "gotcha" (suffered by all non-functional languages, ones which have mutable objects and, of course, references). A frequently seen bug in beginners' Python code is misusing a default value which is mutable, e.g.:
def addone(item, alist=[]):
alist.append(item)
return alist
This code may be correct if the purpose is to have addone keep its own state (and return the one growing list to successive callers), much as static data would work in C; it's not correct if the coder is wrongly assuming that a new empty list will be made at each call.
Raw beginners used to functional languages can also be confused by the command-query separation design decision in Python's built-in containers: mutating methods that don't have anything in particular to return (i.e., the vast majority of mutating methods) return nothing (specifically, they return None) -- they're doing all their work "in-place". Bugs coming from misunderstanding this are easy to spot, e.g.
alist = alist.append(item)
is pretty much guaranteed to be a bug -- it appends an item to the list referred to by name alist, but then rebinds name alist to None (the return value of the append call).
While the first issue I mentioned is about an early-binding that may mislead people who think the binding is, instead, a late one, there are issues that go the other way, where some people's expectations are for an early binding while the binding is, instead, late. For example (with a hypothetical GUI framework...):
for i in range(10):
Button(text="Button #%s" % i,
click=lambda: say("I'm #%s!" % i))
this will show ten buttons saying "Button #0", "Button #1", etc, but, when clicked, each and every one of them will say it's #9 -- because the i within the lambda is late bound (with a lexical closure). A fix is to take advantage of the fact that default values for argument are early-bound (as I pointed out about the first issue!-) and change the last line to
click=lambda i=i: say("I'm #%s!" % i))
Now lambda's i is an argument with a default value, not a free variable (looked up by lexical closure) any more, and so the code works as intended (there are other ways too, of course).
I stumbled upon this one recently again, (after years of python) while trying to remove a small dependency on numpy.
If you come from matlab you should use and trust numpy functions for mono-type array handling. Along with matplotlib, they are some very convenient packages for a smooth transition.
import numpy as np
np.zeros((4,)) # to make an array full of zeros [0,0,0,0]
np.zeros((4,1)) # another one full of zeros but 2 dimensions [[0],[0],[0],[0]]
np.zeros((4,0)) # an empty array like [[],[],[],[]]
np.zeros((0,4)) # another empty array, which can not be represented with python lists o_O
etc.