Function in Python Setting Global Variables (without intent) - function

I don't know if this is a problem that others get, but I have code in python that goes like this:
def makemove(board,move,val):
new=board
new[move[0]][move[1]]=val
return new
My problem is that if I use this function by simply doing makemove(game,[0,1],-1) where game equals [[0,0,1],[0,1,0],[1,0,0]] the variable game becomes [[0, -1, 1], [0, 1, 0], [1, 0, 0]].
I have tried to look into functions setting global variables, but I have thus for not found a way to prevent makemove() from setting the variables that you put into it. Is there something obvious that I'm missing?

You need to clone board.
import
new = copy.deepcopy(board)
see https://stackoverflow.com/a/2612815/93910 for other ways of doing this.
Your code sets elements of a variable which is a "reference".
In other words, your variable new is really an array reference to board, i.e. it points to the same memory location. So when you change new, the original variable board gets changed.
Here's another answer on how to think about this: https://stackoverflow.com/a/9697367/93910

This is basically because assignment in Python doesn't mean what you think it does, and lists are mutable sequences.
Lists are Python objects. The name board is merely a label for or reference to that object.
So when you say new=board this means "let the name new reference the same object as the name board".
In Python every object has a unique identifier that you can retrieve using id(). Let's create a board, do the assignment and see what happens:
In [1]: board = [[0,0,1],[0,1,0],[1,0,0]]
In [2]: new = board
In [3]: id(new), id(board)
Out[3]: (34495504136, 34495504136)
new and board are referencing the same object.
Since a list is a mutable sequence you can change it without getting an error.
So if you want to play with any mutable sequence inside a function without modifying the original, you should use copy.deepcopy first to make a copy and modify that.

Related

How do I keep a variable consistant even after seperate play sessions?

I have a variable area which stores a number.
When the app is restarted, it is reset back to it's original value. How can I keep area persistent after being closed?
I'm using Flash CS6 for Android
You'll have to save the variable. There's multiple ways to do this but using a SharedObject is the easiest IMO.
First thing is you don't actually create a new instance of the SharedObject class, you instead call the static function getLocal and this sets your variable. So somewhere near the start of your program you'll want something like this:
var gameSave:SharedObject = SharedObject.getLocal("gameSave");
This either creates a new locally persistent shared object if one does not exist or it grabs the one with the same initialized name ("gameSave") on your computer. This way you can access the saved variables across multiple playthroughs.
Now to save a variable you simply use the dataObject on the shared object and write values to it, then you call the function flush when you're done writing values to immediately save the shared object to your computer.
So saving your area value would look something like this:
gameSave.data.area = Main.area;
gameSave.flush();
After that you'll want to set the area value to whatever the saved value is when your game launches:
if (gameSave.data.area !== undefined) Main.area = gameSave.data.area;
We check if the value is undefined because it might not exist yet if you're playing the game for the first time and the area hasn't been saved yet.
Last thing in case you want to expand the scope of this and save more values: you can only write specific values to the shared object. The way I understand it is you can only write certain class types and primitives. If you try to write anything that's not a primitive or the exception classes, it'll automatically convert that item to an Object and it more or less becomes useless. The classes that it can accept that you'll probably use the most are: int, uint, Number, String, Boolean, Object, and Array. It has a few others like ByteArray and XML, but you'll either not use those at all or not use them very frequently. If you want to save any other class type you'll have to add that functionality yourself.

Tensorflow 1.1 Error : Attempt to reuse RNNCell with a different variable scope than its first use

I am trying to run the seq2seq translate example present on Tensorflow website and getting following error. I am using tensorflow-gpu==1.1.0
ValueError: Attempt to reuse RNNCell
with a different variable scope than its first use.
First use of cell was with scope
'embedding_attention_seq2seq/embedding_attention_decoder/attention_decoder/gru_cell',
this attempt is with scope 'embedding_attention_seq2seq/rnn/gru_cell'.
Please create a new instance of the cell if you would like it to use a
different set of weights. If before you were using:
MultiRNNCell([GRUCell(...)] * num_layers), change to:
MultiRNNCell([GRUCell(...) for _ in range(num_layers)]). If before
you were using the same cell instance as both the forward and reverse
cell of a bidirectional RNN, simply create two instances (one for
forward, one for reverse). In May 2017, we will start transitioning
this cell's behavior to use existing stored weights, if any, when it
is called with scope=None (which can lead to silent model degradation,
so this error will remain until then.)
On github people were suggesting to change the add the reuse argument to cell as follows :
def single_cell():
return tf.contrib.rnn.GRUCell(size, reuse = tf.get_variable_scope().reuse)
if use_lstm:
def single_cell():
return tf.contrib.rnn.BasicLSTMCell(size, reuse = tf.get_variable_scope().reuse)
cell = single_cell()
if num_layers > 1:
cell = tf.contrib.rnn.MultiRNNCell([single_cell() for _ in range(num_layers)])
But still I am getting the same error. What's the issue and how to resolve it ?
Any help is highly appreciated.
P.S: A similar post was there on stackoverflow,but that solution didn't work for me and since the version of TF is different, I created a new post.

Provide mean pixel values to Caffe's python classify.py

I'd like to test a Caffe model with the Python wrapper:
python classify.py --model_del ./deploy.prototxt --pretrained_model ./mymodel.caffemodel input.png output
Is there a simple way to give mean_pixel values to the python wrapper? It seems to only support a mean_file argument?
The code makes use of args.mean_file variable to read a numpy format data to a variable mean. The easiest method will be to bring on a new parser argument named args.mean_pixel which has a single mean value, store it a mean_pixel variable, then create an array called mean which has the same dimensions as that of input data and copy the mean_pixel value to all the elements in the array. The rest of the code will function as normal.
parser.add_argument(
"--mean_pixel",
type=float,
default=128.0,
help="Enter the mean pixel value to be subtracted."
)
The above code segment will try to take a command line argument called mean_pixel.
Replace the code segment:
if args.mean_file:
mean = np.load(args.mean_file)
with:
if args.mean_file:
mean = np.load(args.mean_file)
elif args.mean_pixel:
mean_pixel = args.mean_pixel
mean = np.array([image_dims[0],image_dims[1],channels]) #where channels is the number of channels of the image
mean.fill(mean_pixel)
This will make the code to pick the mean_pixel value passed on as an argument, if mean_file is not passed as an argument. The above code will create an array with the dimensions as that of the image and fill it with the mean_pixel value.
The rest of the code needn't be changed.

AS3: how to pass by "object"

I was actually looking for a way to pass by reference in AS3 but then it seemed that adobe and lots of people's understanding of pass by reference is different from what I have been taught at the university. I was taught java was pass by value and C++ allowed pass by reference.
I'm not trying to argue what pass by value and reference are. I just want to explain why I'm using pass by object in the question...
Back to the question, I would like to do something like:
public function swapCard(cardA:Cards, cardB:Cards) {
var temp:Cards = cardA;
cardA = cardB;
cardB = temp;
}
...
swapCard(c1, c2);
EDIT: adding two examples on how I'm using the swapCard function
1) in the process of swaping a card between player1 and player2's hand
swapCard(player1.hand[s], player2.hand[t]);
2) in the process of swaping a card between player1's hand and deck
swapCard(player1.hand[s], player1.deck[rand]);
In C++, we only need to add a symbol before the parameters to make it work (and we call THIS pass by reference). But in AS3, cardA and cardB are just pointers to the formal parameters. Here in the function, changing the pointers does not do anything to the formal parameters :(
I have been searching for hours but I couldn't find a way to without knowing all the properties of the Cards.
If I have to change the properties of the cards one by one then maybe I should change swapCard to a static function in class Cards? (because I don't want to expose everything to another class) I'm not sure if this is a good practice either. This is like adding a swap_cars function into class Cars. If I let this happen, what will be next? Wash car, lend car, rent car... I really want to keep the Cards class clean and holds only the details of the card. Is there a possible way to do this properly in AS3?
The kind of swap function that you're trying to implement is not possible in AS3. The input parameters are references to the input objects but the references themselves are passed by value. This means that inside the function you can change the cardA and cardB but those changes will not be visible outside the function.
Edit: I added this portion after you edited your question with sample usage.
It seems like you're trying to swap two objects in 2 different arrays at given array positions in each - you can create a function for this in AS3 but not the way you attempted.
One possible implementation is to pass the arrays themselves and the positions that you're trying to exchange; something like this:
// Assumes arrays and indices are correct.
public function SwapCards(playerHand:Array, playerCardIndex:int,
playerDeck:Array, playerDeckIndex:int):void
{
var tempCard:Card = playerHand[playerHandIndex];
playerHand[playerHandIndex] = playerDeck[playerDeckIndex];
playerDeck[playerDeckIndex] = tempCard;
}
Note that you still exchange references and the arrays themselves are still passed by reference (and the array references are passed by value - you could, if you wanted, change the arrays to new arrays inside this function but you wouldn't see new arrays outside). However, because the array parameters refer to the same arrays inside and outside the function, you can make changes to the contents of the array (or other array properties) and those changes will be visible outside.
This solution is faster than cloning the card because that involves allocating memory for a new Card instance (which is expensive) and that temporary instance will also have to be freed by the garbage collector (which is also expensive).
You mentioned in a comment that you pass cards down to lower levels of code - if you don't have a back reference to the arrays (and the positions of the cards), you will not be able to easily swap cards - in AS3, all input parameters are copies (either the copy of the value for primitive types or the copy of the reference for complex objects - changes to the input parameters in a function will not be visible outside).
EDIT: renaming the function from clone to copyFrom as pointed out by aaron. Seems like clone is supposed to be used as objA = objB.clone()
At this point, I'm adding a copyFrom() function in the Cards class such that
var temp:Cards = new Cards(...);
var a:Cards = new Cards(...);
...
temp.copyFrom(a);
...
temp will be copying everything from a.
public function swapCard(cardA:Cards, cardB:Cards) {
var temp:Cards = new Cards();
temp.copyFrom(cardA);
cardA.copyFrom(cardB);
cardB.copyFrom(temp);
}
I will wait for a week or so to see if there are any other options
You have some good answers already, but based on the comments back-and-forth with me, here's my suggestion (I use "left" and "right" naming because it helps me visualize, but it doesn't matter):
function swapCard(leftCards:Array, leftCard:Card, rightCards:Array, rightCard:Card):void {
var leftIndex:int = leftCards.indexOf(leftCard);
var rightIndex:int = rightCards.indexOf(rightCard);
leftCards[leftIndex] = rightCard;
rightCards[rightIndex] = leftCard;
}
Now you can swap the cards in the two examples you posted like this:
swapCard(player1.hand, player1.hand[s], player2.hand, player2.hand[t]);
swapCard(player1.hand, player1.hand[s], player1.deck, player1.deck[rand]);
However, note that while this swaps the cards in the arrays, it does not swap direct references to the cards in those arrays. In other words:
var a:Card = player1.hand[0];
var b:Card = player2.hand[0];
swapCard(player1.hand, a, player2.hand, b);
// does not change the references a and b, they still refer to the same card
a == player2.hand[0];
a != player1.hand[0];
b == player1.hand[0];
b != player2.hand[0];
Typically, this sort of thing is handled by dispatching a "changed" event so that any code that cares about the state of a player's hand array will know to re-evaluate the state of the hand.
There's a deep misunderstanding going on here. The question is about object reference but the PO is not trying to swap any Object reference at all.
The problem comes from the fact that the PO does not understand the difference between variable and objects. He's trying to swap variable/object reference which is not dynamically possible of course. He wants with a function to make the variable holding a reference to Object A, swap its object reference with another variable. Since Objects can be passed around but not variables (since they are just holders (not pointers)) the task is not possible without a direct use of the given variable.
To resume:
variables are not Objects!
variables hold a reference to an object.
variables cannot be passed in function or referenced in functions because THEY ARE NOT OBJECTS.

method .attachMovie() is no longer supported .Flash to AS3 conversion

I am completing an online tutorial and manipulating it suit my website. I've come across this code...
`// Create a menu item movie clip in the menu_mc instance on the main timeline
// for each item element offsetting each additional further down the screen
var item_mc = menu_mc.attachMovie("movieitem","item"+item_count, item_count);
item_mc._x = item_count * item_spacing;
item_count++;`
The following line gives me a problem (the method is no longer supported)
var item_mc = menu_mc.attachMovie("movieitem","item"+item_count, item_count);
How can i achieve this?
I've tried the following with no joy. message too many arguments?
var mItem:movieitem = new movieitem;
var item_mc = menu_mc.addChild(mItem,mItem+item_count, item_count);
addChild() only accepts 1 argument, which is the display object itself. Also, it looks like you're missing brackets when you create your object and by convention, class names are capitalised.
var mItem:movieitem = new movieitem();
Edit based on my comment
Looking at the documentation for attachMovie() for AS2 (wow, been awhile since I've looked at this), it takes in 3 arguments:
id:String, name:String, depth:Number
Now the id is used to grab a movieclip from the library. This is no longer needed as you've already created a movieclip object from your library in the line before:
var mItem:Movieitem = new Movieitem();
The second argument name is used to create a unique instance name for the created moviclip from the library. You don't really need this. In the line where you create the movieclip (see above), you already have a unique reference you can use to access the movieclip. Interestingly, attachMovie() also returns a reference -I've never ever found a use for the instance names given with the 'name' argument. I just use the reference returned to access it, which you are already doing.
The third argument depth determines which depth the movieclip is placed at. In your case, I am guessing that ' item_count' is just a number that increases, which effectively puts that movie clip at the highest depth when that line is executed. By default, addChild() will automatically do this for you and put the display object (your movieclip) at the highest depth within the parent at the time it is added. So, unless you wanted it at a specific depth/overlapping order, you don't really need to pass this in either. If you did want to add something at a specific depth, look at addChildAt()
Hence as mentioned before, you can just pass in the reference to your movieclip/display object in to addChild().