Confused on variable scope in classes and modules ; python - python

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).

Related

How to create constant C like struct objects under a namespace in Python

I want to create constant objects of a class that I can use again and again in other classes and functions
# Simple C like struct
class data:
def __init__(self,a,b)
self.a = a
self.b = b
# Constant objects in a namespace ??
class DATA_CONSTANTS:
DATA1 = data(0,0)
DATA2 = data(3,5)
DATA3 = data(43, 23)
If I now want to use DATA_CONSTANTS.DATA1, will it be created on first call or everytime I refer to this object ?
What I am looking for is something like in C++ where you create constant objects in a global or given namespace that can be reused as a constant object with fully qualified name say DATA_CONSTANTS::DATA1 or DATA_CONSTANTS::DATA2 etc.
However I am not sure what I am doing above is a pythonic way to accomplish the same in Python. Is this correct ?
Variables declared in the upper level of a class are class variables, and are only created once at the site that they're declared, then they remain constants. You can see this for yourself:
def calc_value():
print("computed the value")
return 1
class Foo:
my_var = calc_value()
print(Foo.my_var + Foo.my_var)
# prints "computed the value" then 2

How to import global variables in python from a class module in another file?

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

"Undeclared variable" declaration in python

The following code is an example:
class A(object):
def f(self):
pass
A.f.b = 42
How is this variable being allocated? If I declare A.f.a, A.f.b, and A.f.c variables am I creating 3 different objects of A? Can someone explain what's going on in memory (as this does not appear to be something easily coded in C)?
The following only works in Python 3:
class A(object):
def f(self):
pass
A.f.a = 41
A.f.b = 42
A.f.c = 43
A.f is an object of type function, and you have always been able to add new attributes to a function object. No instances of A have been created; the three attributes are referenced from the function f itself.
If you had two instances a1 = A() and a2 = A(), however, neither a1.f.b and a2.f.b are defined, because a1.f is not a reference to A.f; it is a reference to an object of type method. This results from how Python's descriptor protocol is used to implement instance methods.
A.b = 42 adds a class variable to A, and thus makes it visible instantly for each instance of A (but only 1 entry in memory)
You can add attributes to classes and instances anytime you like in Python. The cleanest way would be to do it a declare time or this could be misleading.
class A:
b = 12
But for quick "extensions" of classes or instances you could choose to dynamically add them.
ex:
class A(object):
pass
a = A()
print('b' in dir(a)) # False
A.b = 42
print('b' in dir(a)) # True even if instanciated before creation of `b`

Python: How to make variables consistent throughout different functions?

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()

Strange variable in class

I'm trying to understand Python's classes and for that I created this simple program:
class TestClass(object):
b = 3
def __init__(self):
self.a = 1
print '*** INIT ***'
print self.a, TestClass.b
print
def set_all(self):
self.a *= 2
TestClass.b *= 2
def print_all(self):
print 'PrintAll'
print self.a, TestClass.b
print
def main():
c = TestClass()
c.a *= 10
TestClass.b *= 10
c.b *= 10
print c.a, TestClass.b, c.b
print
c.print_all()
c.set_all()
print c.a, TestClass.b, c.b
TestClass.b
c.b
if __name__ == '__main__':
main()
I already understood that var c.a is an instance var. Var TestClass.b is a class/static var.
My 1st question is what is var c.b?
The program shows that it is different than TestClass.b.
My 2nd question is when should I use class/static vars instead of instance vars?
Thanks,
JM
To answer your first question, c.b is initially another name for TestClass.b, because no b attribute exists on the instance c. However, as soon as you do an assignment to it by that name (as you do with c.b *= 10), you create a new instance variable b on the c instance which shadows the class variable b. From then on c.b is unrelated to TestClass.b and works just like any other instance variable.
As to your second question, there are a few times where class variables are useful. Perhaps the most common is for class constants, which are not expected to change throughout the running of the program. Python doesn't have any easy way to actually prevent other users from reassigning them, but if you name them in ALL_CAPITOLS and document that they're intended to be constant anyone who messes with them deserves any bugs they cause. Putting the constants in the class means that you don't need to recalculate them over and over for each instance (or worse, for each call to a method).
Another use of class variables is for bookkeeping, such as counting the number of objects of a class that have been created. This can be useful if each instance needs a unique ID number, just copy the current count into an instance variable! Other situations come up when you want to have only a limited number of instances (often just a single one, as a Singleton). You can store that instance in a class variable and return it from __new__, to prevent other instances from being created.
Some programmers like to use class variables as default values for instance variables that may be created later to shadow them (as in question 1). While this isn't forbidden by Python's language design, I tend not to like this style of code as it can be confusing to see a method refer to something that looks like an instance variable which doesn't exist yet. It can also get badly broken if you use mutable objects as the class variable defaults. I think it's better to stick with instance variables from the start, assigning them default values as necessary in __init__.
To answer your second question, static variables are used to contain some general information about the class. For a simple example, let us say that you have a Student class which holds the info about the students in some class. You use an instance variable "marks", to keep track of object specific data. i.e. Marks of each student.
Whereas, if you want to keep track of the number of students you have, a static variable comes in handy here. So, the static variable can be increased whenever an object is created, and Student.count will give you the number of objects created.
Hope this helps...
As for your first question, I don't think TestClass.b is different from c.b. This is what I tried:
>>> class A:
... b = 3
... def __init__(self):
... self.a = 1
... A.b += 1
... print self.a,A.b
...
>>> c = A()
1 4
>>> c.b
4
>>> d = A()
1 5
>>> d.b
5
>>> c.b
5

Categories