I have a custom Sympy cSymbol class for the purpose of adding properties to declared symbols. This is done as follows:
class cSymbol(sy.Symbol):
def __init__(self,name,x,**assumptions):
self.x = x
sy.Symbol.__init__(name,**assumptions)
The thing is that when I declare a cSymbol within a function (say, it affects the property x of a cSymbol declared outside the function if the names are the same (here "a"):
def some_function():
dummy = cSymbol("a",x=2)
a = cSymbol("a",x=1)
print(a.x) # >> 1
some_function()
print(a.x) # >> 2, but should be 1
Is there a way to prevent this (other than passing distinct names) ? Actually I am not sure to understand why it behaves like this, I thougt that everything declared within the function would stay local to this function.
Full code below:
import sympy as sy
class cSymbol(sy.Symbol):
def __init__(self,name,x,**assumptions):
self.x = x
sy.Symbol.__init__(name,**assumptions)
def some_function():
a = cSymbol("a",x=2)
if __name__ == "__main__":
a = cSymbol("a",x=1)
print(a.x) # >> 1
some_function()
print(a.x) # >> 2, but should be 1
You aren't creating a local Python variable in the subroutine, you are create a SymPy Symbol object and all Symbol objects with the same name and assumptions are the same. It doesn't matter where they are created. It sounds like you are blurring together the Python variable and the SymPy variable which, though both bearing the name "variable", are not the same.
Related
I have a file that contains the class definitions and functions I need to use in my main file to make the text cleaner. However, I'm having a problem with imported global variables.
There is plenty of information at SO and other resources regarding how to make function variables global within the same code or how to use the global variables from an imported file. However, there is no information on how to access a variable from an imported file if the variable belongs to a function belonging to a class.
I would appreciate any help on how to do it or why it cannot be done. Please skip the lecture on the dangers of using global variables like this as my situation requires such use.
Edit: Sorry for not having an example in the original post. It's my first one. Below is an example of what I'm trying to accomplish.
Let's say I have a file classes.py that contains:
class HelixTools():
def calc_angle(v1, v2):
v1_mag = np.linalg.norm(v1)
v2_mag = np.linalg.norm(v2)
global v1_v2_dot
v1_v2_dot = np.dot(v1,v2)
return v1_v2_dot
Then in my main text file I do:
from classes import HelixTools
ht = HelixTools()
v1 = some vector
v2 = some other vector
ht.calc_angle(v1,v2)
print(v1_v2_dot)
The result is "v1_v2_dot" not defined. I need v1_v2_dot to use it as the input of another function.
Here's an example of how you can access class attributes (if I understand what it is you want to do correctly). Lets imagine you have a python file called "Test_class.py" that contains the following code:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def bar(self):
self.z = self.x + self.y
Now lets imagine you want to import this class into another python file in the same directory, and access attributes of that class. You would do this:
from Test_class import Foo
# Initialize two Foo objects
test1 = Foo(5, 6)
test2 = Foo(2, 3)
# Access the x and y attributes from the first Foo object
print(test1.x) # This will print 5
print(test1.y) # This will print 6
# Access the x and y attributes from the second Foo object
print(test2.x) # This will print 2
print(test2.y) # This will print 3
# Access the z attribute from the first Foo object
test1.bar()
print(test1.z) # This will print 11
# Access the z attribute from the second Foo object
test2.bar()
print(test2.z) # This will print 5
This works because variables defined in the __init__ magic method are initialized as soon as the Foo object is first called, so the attributes defined here can be access immediately after. The bar() method has to be called before you can access the z attribute. I made 2 Foo objects just to show the importance of including "self." in front of your variables, in that each attribute is specific to that particular class instance.
I hope that answers your question, but it would be very helpful if you provided some example code to show exactly what it is you want to do.
You should likely use a class attribute to store this value. Note that the implementation will depend on what your class HelixTools really does.
But for the example, you could use something like this:
import numpy as np
class HelixTools():
def __init__(self):
# Initialize the attribute so you'll never get an error calling it
self.v1_v2_dot = None
def calc_angle(self, v1, v2): # Pass self as first argument to this method
v1_mag = np.linalg.norm(v1)
v2_mag = np.linalg.norm(v2)
# Store the value in the attribute
self.v1_v2_dot = np.dot(v1,v2)
And then:
from classes import HelixTools
ht = HelixTools()
v1 = some vector
v2 = some other vector
ht.calc_angle(v1,v2) # This will not return anything
print(ht.v1_v2_dot) # Access the calculated value
Is there any way to somehow import a module, assign a variable in it, then use that variable in the program I imported with? I've probably explained that badly, for example
foo.py =
def main():
x = 1
then, in another program,
import foo
foo.main()
print(x)
This, of course, doesn't work, is there
any way to pull this off?
In the example you give, there is no x ... by the time you get back to try to print it. Its gone out of scope.
You do have some options, one of which is to return it:
foo.py =
def main():
x = 1
return x
And then elsewhere:
import foo
x = foo.main()
print(x)
#quamrana covers the sensible way to do this - with return values - but you can also straight-up use global variables. Say, we have two source files:
foo.py:
x = 0
def main():
global x
x = 1
and
bar.py:
import foo
print(foo.x) # should print 0
foo.main()
print(foo.x) # should print 1
The global keyword in foo.py's main() function is necessary to make sure that x is perceived as a global variable (belonging to the module foo) rather than a local variable (belonging to the function main()).
Then, in bar.py, we have to address x as foo.x, because x belongs to foo. You could also use named imports to circumvent that:
from foo import x, main
print(x) # should print 0
main()
print(x) # should print 1
I'm still starting out how to program in Python, and I'm just wondering how to make a variable consistent throughout different functions. For example, a function that I've made modified a variable. Then, I've used that variable again in another function. How can I make the modified variable appear in the 2nd function? When I try it, the 2nd function uses the original value of the variable. How can you make it use the modified value? Do I need to use global variables for this?
Also, is the input() function recommended to be used inside functions? are there any side effects of using it inside them?
The variables need to be shared by a scope that is common to both functions, but this need not necessarily be a global scope. You could, for instance, put them in a class:
class MyClass:
def __init__(self):
self.x = 10
def inc(self):
self.x += 1
def dec(self):
self.x -= 1
mc = MyClass()
print mc.x # 10
mc.inc()
print mc.x # 11
mc.dec()
print mc.x # 10
What scope exactly the variable should exist in depends on what you're trying to do, which isn't clear from your question.
Use global variabale to access variable throughout code.
Demo:
>>> a = 10
>>> def test():
... global a
... a = a + 2
...
>>> print a
10
>>> test()
>>> print a
12
>>>
In class, use class variable which is access to all instance of that class. OR use instance variable which is access to Only respective instance of the class.
You can use return in the function.
x = 3
def change1():
x = 5
return x
x = change1()
def change2():
print(x)
change1()
change2()
You can use the global keyword at the top of the function to let python know that you are trying to modify the variable in global score. Alternatively, you could use OOP and classes to maintain an instance variable throughout class functions.
x = 5
def modify():
global x
x = 3
modify()
I'm trying to write a module that contains multiple classes. I want the same variable name in every class but want the values to be different. So that every definition will use the variable defined in the top of its own class.
For example:
class assign():
global a , b
a = 1
b = 2
def aa(x):
return a*x
class assign1():
global a, b
a = 5
b = 10
def aa(x) :
return a*x
This Produces:
print(assign.aa(3))
=15
print(assign1.aa(3))
=15
The global values aren't switch between the different classes and I would like them to be.
Interesting -- I've never seen global in the class namespace before ... Basically what happens is when you create your class, you add a and b to the global namespace. Then, in your method call, you pick up a from the global namespace (because there is no local variable a). What you probably wanted is:
#while we're at it, get in the habit of inheriting from object
# It just makes things nicer ...
class assign(object):
a = 1
b = 2
def aa(self,x):
return self.a*x
class assign1(object):
a = 5
b = 10
def aa(self,x) :
return self.a*x
Now, when you call the aa method, python will first look for an attribute a on the instance. When it's not found on the instance, the class will be checked (and used since the classes both have an a attribute).
def main():
x=2
def cool():
y=4
nonlocal x
print (x)
It is showing an error as --nonlocal x is a invalid syntax--.And if I dont declare it as nonlocal it says undefined x. So, how do i acess a variable which is in some other function ?Now how do i access x variable which is defined at main().
You can't.
You shouldn't. Doing so would just make it hard to read code because code from anywhere could read and modify your variables. By keeping access restricted to the one function it is easier to follow.
You do not. The variables local to a function only exist while that function is running; so once main has returned, its x does not exist. This also ties in to the fact that a separate call to the function gets a separate variable.
What you describe is a bit like reading the value of a static variable in C. The difference with static variables is that they're independent of the call; they still exist, and that makes most functions that use them non-reentrant. Sometimes this is emulated in Python by adding a default argument with a mutable value, with the same downsides.
In CPython, you actually can find out what the local variables of a pure Python function are by inspecting its code object, but their values will only exist in the call itself, normally on a call stack.
def func():
x=2
import dis
print func.__code__.co_varnames
dis.disassemble(func.__code__)
yields:
('x',)
2 0 LOAD_CONST 1 (2)
3 STORE_FAST 0 (x)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
So x is actually local variable 0.
I would suggest looking up a debugger for details on call stack inspection.
Once you start needing attributes on a function, turn it into a functor:
class MainFactory(object):
def __call__(self):
self.x = 4
main = MainFactory() # Create the function-like object main
main() # call it
print main.x # inspect internal attributes
A functor in python is simply a normal object whose class implements the special __call__ method. It can have an __init__ method as well, in which you may pre-set the values of attributes if you wish. Then you can create different "flavours" of your functor by supplying different arguments when instantiating:
class MainFactory(object):
def __init__(self, parameter=1):
self.parameter = parameter
def __call__(self):
self.x = 4 * self.parameter
Now main = MainFactory(2); main() will have main.x set to 8.
Obviously, you can keep unimportant variables of the function inaccessible by simply using local variables instead of attributes of self:
def __call__(self):
# i and p are not accessible from outside, self.x is
for i in range(10):
p = i ** self.parameter
self.x += p
x = 0
def main():
global x
x = 2 # accesses global x
main()
print x # prints 2