How to Make the Value of a Variable Track the Value of Another

How do I keep track of a variable's value when it's passed into a function?

First things first: the line animal = animal++ won't do anything because it is a postfix increment. Either just do animal++ or ++animal to increment it.


Nope, dog will not be changed. JavaScript passes primitives by value (Thanks @ASDFGerte for the correction).

var dog = 0;
function dogStuff(animal) {
animal++;
}
dogStuff(dog);
console.log(dog); // prints 0

What you want to do (probably) is something similar to what @alfasin mentioned: return the updated value of dog.

var dog = 0;
function dogStuff(animal) {
animal++;
return animal;
}
dog = dogStuff(dog);
console.log(dog); // prints 1

However, if you pass an object and reassign its properties, the original object will be modified (almost like pass by reference):

var dog = { age: 0 };
function incrementAge(animal) {
animal.age++;
}
incrementAge(dog);
console.log(dog.age); // prints 1

edit: If you want to assign multiple variables on return, one possible way to do it is to return an array of variables, which can then be assigned with deconstructed assignment:

var dog = 0;
var cat = 52;
function incrementTwoAnimals(animal1, animal2) {
animal1++;
animal2++;
return [animal1, animal2];
}
[dog, cat] = incrementTwoAnimals(dog, cat); // deconstructed assignment
console.log(dog, cat); // prints 1, 53

How do I change the value of one variable based on the value of another variable?

df %>%
mutate(col1 = coalesce(case_when(col2 == 'some text' ~ 2,
col2 == 'some other text' ~ 4), col1),
col2 = str_remove(col2, 'some (other )?text'))
col1 col2
1 1
2 3
3 6
4 2
5 2
6 2
7 2
8 4
9 7 some third text
10 7 Some thrid Text

How do I set the value of a variable based on another variable?

Each variable has a scope in Java. The variable doesn't exist outside of its scope. So technically the emr declared here

if (site == "site1"){
String emr = "sampletext";
}

is not valid here

else if (site == "site2"){
String emr = "domain";
}

because both the emr's in the if and else if blocks have block scope.

However, the emr declared as below

String site = read.nextLine();
String emr;

is valid through out the method as it has method scope. You can read more here

The working code snip is as follows.

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
Scanner read = new Scanner(System.in);
String site = read.nextLine();
String emr;

if (site.equals("site1")){
emr = "sampletext";
} else if (site.equals("site2")){
emr = "domain";
} else {
emr = " ";
}
System.out.print(emr);
}
}

When it comes to comparing Objects such as String you need to be careful. You might want to take a look at the accepted answer here

As @Hleb Shypula pointed, if you want to do away with the last else block, you would want to initialize a default value to emr upfront. Below is the updated code.

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
Scanner read = new Scanner(System.in);
String site = read.nextLine();
String emr = " ";

if (site.equals("site1")){
emr = "sampletext";
} else if (site.equals("site2")){
emr = "domain";
}
System.out.print(emr);
}
}

For loop to assign value to variable based on value of another var

You can use np.where to assign values to 'My_new_status':

df['My_new_status'] = np.where(df['Housing_ID']==1,'valid','')

Output:

   Housing_ID  Member_ID My_new_status
0 1 1 valid
1 1 2 valid
2 1 3 valid
3 1 4 valid
4 1 5 valid
5 2 1
6 2 2
7 3 1
8 3 2
9 3 3

How can I track the values of a local variable in Python?

I had in mind something really simple like this:

#the decorator
def debug_function(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
print('debug:', res)
return res

return wrapper

#proof of concept:
@debug_function
def square(number):
return number*number

class ClassA:
def __init__(self):
self.Number = 42

@debug_function
def return_number(self):
return self.Number

if __name__ == '__main__':
result = [square(i) for i in range(5)]
print(result)

my_obj = ClassA()
n = my_obj.return_number()
print(n)

In short, write a simple decorator that logs the result of your function somewhere (above I only write it out to the terminal, but this could be extended to use a log file or similar). Then you decorate whatever function you want to track and will get its return value whenever the function is called. In the code above I show what it does for a simple function and a class method. The result of the example code looks like this:

debug: 0
debug: 1
debug: 4
debug: 9
debug: 16
[0, 1, 4, 9, 16]
debug: 42
42

EDIT 2:

I edited the code below to use the actual function instead of just its __name__ to store the intermediate values. This should make it somewhat less error prone.

EDIT:

For storing values in memory, I would again go as simple as possible and just store the values in a list. For the simple example outlined above, possibly a global list object would be enough. However, as you most likely want to look at more than one function at a time, I'd rather suggest to design the decorator as a class and store one list per function in a class attribute. More about this in the example code.

The real problem is the storing of local variables. In order to do this you have to change the actual code of your function. Naturally, you don't want to do this 'by hand', but want your decorator to take care of this. Here it becomes tricky. After looking around for a while, I found a package called bytecode (which works at least for Python 3.6). There are most likely other options, but I decided to go with this one. bytecode allows you to translate the python bytecode into human-readable form, modify it, and translate it back to python bytecode. I have to admit that I'm a bit out of my depth here, but what I did was to write a few small functions, look at the translated code and design a piece of code that does what I want.

So, in this example the objective is to decorate the function to be tested, such that the decorator takes a list of strings as argument, where each string is the name of a variable that should be tracked. It then adds code to the function body that packs the final values of all listed variables in a tuple and returns the tuple together with the real return value. The 'wrapper' function then collects the tracked values and appends them to a function-specific list of values which can be read at any point in the code.

So here it goes. Put the actual decorator in its own file, I call it here debug_function.py:

from bytecode import Bytecode, Instr

class debug_function(object):
"""
Decorator that takes a list of variable names as argument. Everytime
the decorated function is called, the final states of the listed
variables are logged and can be read any time during code execution.
"""
_functions = {}
def __init__(self, varnames):
self.varnames = varnames

def __call__(self, func):
print('logging variables {} of function {}'.format(
','.join(self.varnames), func.__name__
))
debug_function._functions[func] = []
c = Bytecode.from_code(func.__code__)
extra_code = [
Instr('STORE_FAST', '_res')
]+[
Instr('LOAD_FAST', name) for name in self.varnames
]+[
Instr('BUILD_TUPLE', len(self.varnames)),
Instr('STORE_FAST', '_debug_tuple'),
Instr('LOAD_FAST', '_res'),
Instr('LOAD_FAST', '_debug_tuple'),
Instr('BUILD_TUPLE', 2),
Instr('STORE_FAST', '_result_tuple'),
Instr('LOAD_FAST', '_result_tuple'),
]
c[-1:-1]= extra_code
func.__code__=c.to_code()

def wrapper(*args, **kwargs):
res, values = func(*args, **kwargs)
debug_function._functions[func].append(values)
return res

return wrapper

@staticmethod
def get_values(func):
return debug_function._functions[func]

Then, let's generate again some functions to be checked, which we decorate with this decorator. Put these, for instance, in functions.py

from debug_function import debug_function

@debug_function(['c','d'])
def test_func(a,b):
c = a+b
d = a-b
return c+d

class test_class:
def __init__(self, value):
self.val = value

@debug_function(['y'])
def test_method(self, *args):
x = sum(args)
y = 1
for arg in args:
y*=arg
return x+y

Finally, call the functions and look at the output. debug_function has a static method called get(), which takes the function you want information on as argument and returns a list of tuples. Each of these tuples contains the final values of all the local variables you wanted to track after one call to that function. The values are in the same order in which they were listed in the decorator statement. With an 'inverse' zip, you can easily separate these tuples.

from debug_function import debug_function
from functions import test_func, test_class

results = [test_func(i,j) for i in range(5) for j in range(8,12)]
c,d = zip(*debug_function.get_values(test_func))
print('results:', results)
print('intermediate values:')
print('c =', c)
print('d =', d)

my_class = test_class(7)
results2 = [
my_class.test_method(i,j,4,2) for i in range(5) for j in range(8,12)
]
y, = zip(*debug_function.get_values(test_class.test_method))
print('results:', results2)
print('intermediate values:')
print('y =', y)

The output of the calls looks like this:

logging variables c,d of function test_func
logging variables y of function test_method
results: [0, 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8]
intermediate values:
c = (8, 9, 10, 11, 9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14, 12, 13, 14, 15)
d = (-8, -9, -10, -11, -7, -8, -9, -10, -6, -7, -8, -9, -5, -6, -7, -8, -4, -5, -6, -7)
results: [14, 15, 16, 17, 79, 88, 97, 106, 144, 161, 178, 195, 209, 234, 259, 284, 274, 307, 340, 373]
intermediate values:
y = (0, 0, 0, 0, 64, 72, 80, 88, 128, 144, 160, 176, 192, 216, 240, 264, 256, 288, 320, 352)

I probably should explain a bit better how this works, please ask if anything stayed unclear. As said before, this decorator only stores the final value of each variable (i.e. the value that variable has after the function code has been executed). If you have a more complex function, you may be interested what the value is at, e.g., each variable assignment -- in this case you'll have to do a bit more work, but it should be doable.

Hope this helps

What happens when you assign the value of one variable to another variable in Python?

As a C++ developer you can think of Python variables as pointers.

Thus when you write spam = 100, this means that you "assign the pointer", which was previously pointing to the object 42, to point to the object 100.

Earlier on, cheese was assigned to point to the same object as spam pointed to, which happened to be 42 at that time. Since you have not modified cheese, it still points to 42.

Immutability has nothing to do with it in this case, since pointer assignment does not change anything about the object being pointed to.

Change value of a variable depending on another in python

Use a dict :

yourdict = {'this':1, 'that':2, ...}
text = yourdict[var]


Related Topics



Leave a reply



Submit