Changing a variable's value inside a class in python - python

I have a variable:
var_1 = 5
I pass it to a class:
class x():
def __init__(self, val):
self.class_var_1 = val
object_1 = x(var_1)
I want to change var_1's value using class x, but it won't change
object_1.class_var_1 = 3
print var_1
5
var_1 isn't copied to object_1.class_var_1 with a reference to var_1.
How do I change var_1's value by changing object_1.class_var_1's value?

Python int is immutable. The object can never change its value. Thus you need to re-bind the name to a different object. You'll need code like this:
var_1 = ...
Substitute whatever you like on the right hand side.

Related

Python multi-instances use the same variable

I want to use a variable for two instances in python.
When a instance update the variable, it also be updated in other instances.
my variable is task_id:
class Task(object): # pragma: no cover
def run_deploy(self, args, **kwargs):
# atexit.register(atexit_handler)
self.task_id = kwargs.get('task_id', str(uuid.uuid4()))
def start_benchmark(self, args, **kwargs):
"""Start a benchmark scenario."""
atexit.register(atexit_handler)
self.task_id = kwargs.get('task_id', str(uuid.uuid4()))
But when I run code, I detected that task_id has different value, I want they have same value.
Please let me know how to do it.
Thanks!
To reference an object in python is trivial. Here is a simple example using a class instance:
class cl:
var1 = 0
def __init__(self, var2):
self.var2 = var2
Lets look at two instances of this class and how they update:
>>> x = cl(1) #
>>> y=x
>>> print(y.var2)
1
>>> y.var2 = 2
>>> print(x.var2)
2
And now comes the crucial part:
>>> x is y
True
Don't forget that ìs is not the same as ==.
The same happens also to var1 for both instances.
In python, everything is a reference. A variable is merely a name you give to a reference to an object. You can give many names to refer to the same object.
This pretty much how python works, and it's exactly what you need here.
E.g.:
a = [] # a reference to an empty list, named "a"
b = a # a reference to the same empty list, named "b"
a.append(5) # modify, through the "a" reference
print(b) # "b" still refers to the same list, which is not empty now
=> [5]

Append/Write with values of an instance

So I'm new to working with classes in python, but this project Euler(q 81) I have is done using classes just to be a bit more tricky? I guess?
I can get the values of a (2n+1 * 2n+1) grid, but I can't work with them to append to another list or even write to a file.
def minSum(matrix):
file = open("pleasedeargodwork.txt", "w")
newList = []
for x in maxtrix.grids:
for y in x:
newList.append(y)
print y,
file.write(y,)
print newList
>>> 1 7 2 5 6 2 9 2 5
>>> TypeError: must be string or read-only character buffer, not instance
>>> <matrix.Supplies instance at 0x0240E9B8>
^^ I would like this last line to give me the values, rather than the instance, but how?
My matrix class looks something like this:
class Matrix:
def __init__(self, grids):
self.size = len(grids) / 2
self.grids = [[Supplies(s) for s in row] for row in grids]
class Supplies:
def __init__(self, supp):
if isinstance(supp, list):
self.value = supp[0]
"Matrix" is the class name, "matrix" is the filename and an argument given to my class minSum to be able to access this file.
If you need to see any more of the matrix file let me know.
Thanks.
Looks like you have another error when you try to write an instance to the text file but here's a way to print the values instead of the instance:
The __repr__ method lets you define what the object looks like when it is printed.
Add a __repr__ method to the Supplies class like so:
class Supplies:
def __init__(self, supp):
if isinstance(supp, list):
self.value = supp[0]
def __repr__(self):
return str(self.value)
Whenever you print a Supplies instance, Python will print its value attribute instead. Note that value is not guaranteed to be defined in the Supplies class so you might want to either initialize it or check before you attempt to convert it to a string in the __repr__ method.
Edit
If you want newList to contain the values of each Supplies instance you could just append the value instead of the instance:
newList.append(y.value)
instead of:
newList.append(y)

Force python subclass init to use subclass variables, not parent class

In the following code:
class A(object):
VALUE = 1
def __init__(self, value=VALUE):
self.value = value
class B(A):
VALUE = 2
i'd expect that B().value should be equal to 2, however:
B().value = 1
Is there an elegant way to define a class hierarchy where child classes can just declare class variables they want to override and have them be defaults for the instance variables? I still want to allow for these to be changed on a per-instance level, eg.
b = B(value=3)
This is another default arguments question. The point is that when you write
def foo(value=VALUE):
the code inside the function is compiled and made into a function object. It is at this time -- not at call time! -- that the default arguments are stored. So by the time you have defined B it is too late: the default value of foo is already set and changing VALUE won't have any effect.
If this seems a strange thing to do, suppose foo was a global function:
default = 3
def foo(x=default): pass
Then any other code, anywhere, could screw up foo by doing
global default
default = 4
This is arguably just as confusing.
To force the lookups to be done at runtime not compile time, you need to put them inside the function:
def foo(value=None):
self.value = self.VALUE if value is None else value
or (not quite the same but prettier)
self.value = value or self.VALUE
(This is different because it will treat any 'falsy' value as a sentinel -- that is, 0, [], {} etc will all be overwritten by VALUE.)
EDIT: #mgilson pointed out another way of doing this:
def foo(**kwargs):
self.value = kwargs.get("value", self.VALUE)
This is neater in that it doesn't require you to make a sentinel value (like None or object(), but it does change the argument specification of foo quite fundamentally since now it will accept arbitrary keyword arguments. Your call.
The default value should not be define in the func declaration line, otherwise, when the python reads this line, the default value will be focused, and whatever you change the VALUE later, the default value will not be changed.
You could write it as follows:
class A:
VALUE = 1
def __init__(self, value=None):
if value is None:
value = self.VALUE
self.value = value
class B(A):
VALUE = 2
print(A().value)
print(B().value)

python member variable of instance works like member variable, and some works like static variable

i'm python newbie, and member variable of class works weird in my python code.
some works like normal variable, but some works like static variable!
class Chaos:
list_value = []
value = "default"
def set_value(self, word):
self.list_value.append(word)
self.value = word
def show(self, num):
print(str(num) + "====")
print("value : " + self.value)
for st in self.list_value:
sys.stdout.write(st)
print("\n=====\n")
a = Chaos()
a.show(0)
a.set_value("A")
a.show(1)
b = Chaos()
a.show(2)
b.show(3)
result
0====
value : default
=====
1====
value : A
A
=====
2====
value : A
A
=====
3====
value : default
A
=====
but the last result of the test is different from what i expected in last test.
There should be no "A" in the 'list_value' of the instance of 'b'.
It was just created, and never have been added 'A' before.
I added 'A' to the instance of 'a', not 'b'.
But the result show me that there are also 'A' in 'b'
More over, the 'list_value' and the 'value' in the class works differently.
It looks like the both have same syntax. why do they work differently?
Those are, in fact, class variables. To create instance variables, initialize them in the __init__ function:
class Chaos:
def __init__(self):
self.list_value = []
self.value = "default"
The reason value is behaving like instance variables is because you're setting it using self.value. When Python sees self.X it looks if there's a property X in your object, and if there is none, it looks at its class. Since you never set self.list_value, it's accessing the class variable, that is shared among all instances, so any modifiations will reflect in every other object.
The key difference is that you are appending to list_value, and you are assigning to value. They are called "class variables". Each instance has its own reference to the class variable, which is why the list is shared. However, when you assign, you are changing that instance's reference to point to a different variable, which explains the behavior of value.
If you are looking for instance variable behavior from list_value, initialize it in the constructor (a class method called __init__) instead.

python binding of variable to particular expression

I am developing a simple application which hava a file Constants.py containing all configuration, it is like this
x = y
during execution of program , the value of y changes , I want value of x o get updated too , automatically, this can be reffered as binding, how can I achieve this
In Python variable names point at values. x=y tells Python that the variable name x should point at the value that y is currently pointing at.
When you change y, then the variable name y points at a new value, while the variable name x still points at the old value.
You can not achieve what you want with plain variable names.
I like KennyTM's suggestion to define x as a function since it makes explicit that the value of x requires running some code (the lookup of the value of y).
However, if you want to maintain a uniform syntax (making all the constants accessible in the same way), then you could use a class with properties (attributes which call getter and setter functions):
Constants.py:
class BunchOConstants(object):
def __init__(self, **kwds):
self.__dict__.update(kwds)
#property
def x(self):
return self.y
#x.setter
def x(self,val):
self.y=val
const=BunchOConstants(y=10,z='foo')
Your script.py:
import Constants
const=Constants.const
print(const.y)
# 10
print(const.x)
# 10
Here you change the "constant" y:
const.y='bar'
And the "constant" x is changed too:
print(const.x)
# bar
You can change x also,
const.x='foo'
and y too gets changed:
print(const.y)
# foo
If you change the value (object) itself, then all references to it will be updated:
>>> a = []
>>> b = a # b refers to the same object a is refering right now
>>> a.append('foo')
>>> print b
['foo']
However, if you make the name point to some other object, then other names will still reference whatever they were referencing before:
>>> a = 15
>>> print b
['foo']
That's how python works. Names are just references to objects. You can make a name reference the same object another name is referencing, but you can't make a name reference another name. Name attribution using the = operator (a = 15) changes what a refers to, so it can't affect other names.
if your configuration values are inside a class, you could do something like this:
>>> class A(object):
... a = 4
... #property
... def b(self):
... return self.a
...
then, every time you access b, it will return the value of a.
There is a simple solution you can do. Just define a property and ask for the fget value you defined.
For example:
a = 7
#property
def b():
return a
if you ask for b, you will get something like this <property object at 0x1150418> but if you do b.fget(), you will obtain the value 7
Now try this:
a = 9
b.fget() # this will give you 9. The current value of a
You don't need to have a class with this way, otherwise, I think you will need it.

Categories

Resources