This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 9 years ago.
This doesn't work: (global name 'a' is not defined)
if True:
a = 3
else:
a = 4
print a
This works:
class A:
def f(self):
if True:
a = 3
else:
a = 4
print a
A().f()
This doesn't work: (global name 'a' is not defined)
class A:
def __init__(self):
a = 3
def f(self):
print a
A().f()
Why is it working in one case and not in another ? I thought that if it works in case (2) then it is because a gets in the class context, but this doesn't make it work in (3)
I saw other discussions but I don't understand everything that is said and cases vary a bit.
EDIT:
example 1 does NOT work, at least in a python 2.7 interpreter. This is why it examples 1 and 2 are contradictory
When you create a variable within a function, like this
def __init__(self):
a = 3
it will be accessible only within that function. That's why both 1 and 2 are working. In the third case, you creating a local variable in one function and trying to access it in another function where the variable is not visible. That's why it fails.
In order to make the third case working, add the variable to the current object (self), like this
def __init__(self):
self.a = 3
And this has to be accessed with the current object only
def f(self):
print self.a
Edit:
Regarding the first statement, if you execute the if..else and the print statements like this, it works fine
>>> if True:
... a = 3
... else:
... a = 4
...
>>> print a
3
In the third example, a is a local variable in __init__ and is discarded when that method ends. Within classes, you need to use self.a to keep it around:
class A:
def __init__(self):
self.a = 3
def f(self):
print self.a
Your other examples actually both work, because in both a is defined locally and printed within the same scope. To copy-paste example 1 from my interpreter (2.7.3):
>>> if True:
a = 3
else:
a = 4
>>> print a
3
Related
I am new to Python and didn't find an answer to the following problem:
I have two classes and want them to use variables from each other. Is there a simple way to do this because if I do it like this class a does not know that class b exists.
class a:
y=1
print(b.x)
class b:
x=1
print(a.y)
And how do I use overwrite the variables, the following code does not work:
class a:
y=b.x
class b:
x=1
You are executing print as part of the class definition. It executes as soon as python sees that line of code, before it's read the part about class b.
Instead, use functions inside the classes to execute code after the classes have been defined:
class a:
y=1
def go():
print(b.x)
class b:
x=1
def go():
print(a.y)
a.go()
b.go()
As I said in a comment, your code isn't making effective use of classes. Here's what I think would be better approach that offers more flexibility in working around the circular reference issue.
First the class definitions (which follow the PEP 8 naming convention guidelines):
class A:
def __init__(self, value, linked_value=None):
self.y = value
if isinstance(linked_value, B):
self.linked_value = linked_value.x
def print_linked_value(self):
print(self.linked_value)
class B:
def __init__(self, value, linked_value=None):
self.x = value
if isinstance(linked_value, A):
self.linked_value = linked_value.y
def print_linked_value(self):
print(self.linked_value)
Definitions like that provide two ways to set up the circular references:
By creating them separately, then explicitly linking them:
# First create instances of each class.
a = A(1)
b = B(42)
# Then link them.
a.linked_value = b.x
b.linked_value = a.y
a.print_linked_value() # -> 42
b.print_linked_value() # -> 1
*OR* by creating the first one without a linked value and leaving only the second needing to be linked manually.
# First create instances of each class, but link the second to the first
# when it's created.
a = A(1)
b = B(42, a) # Create and link to first.
# Then link the first to the second to complete the circular references.
a.linked_value = b.x
# Same result.
a.print_linked_value() # -> 42
b.print_linked_value() # -> 1
Final note: Another, more advanced alternative that can also be applied in situations like this by using the built-in property() function as a decorator to create "descriptors". Here's an answer to a somewhat related question that illustrating its use.
class A:
y = 1
def foo(self):
print B.x
class B:
x = 1
def bar(self):
print A.y
>>> A().foo()
2
>>> B().bar()
1
Use 'print' in some function definition.
This question already has answers here:
Copy constructor in python?
(8 answers)
Closed 6 years ago.
In C++, the constructor of a class allows an instance to be constructed from another instance. e.g.
C::C(const C & c) {
bala...;
cc = c.cc;
}
In Python, what is the similar way of doing this? How may I use
c1 = C()
c2 = C(c1)
?
We don't mention the type while defining a variable in python. For example: if x=4, you can always set x to something else, x="shasha". No problem at all.
Note we can not overload a method in python.
Coming back to your question:
Assuming that you understand the python memory management and the difference between a reference and an actual value, You may use deepcopy feature in python:
import copy
class A(object):
def __init__(self):
self.a=10
x = A()
y= copy.deepcopy(x)
x.a=15
print(y.a) # prints 10.
Note that you can always copy one object into another using = operator like y = x but it wont actually copy anything. Now both the references y and x will actually be pointing to the same instance. i.e. if you change anything using one, it will automatically be reflected into the other one:
class A(object):
def __init__(self):
self.a=10
x = A()
y = x
x.a=15
print(y.a) # prints 15.
You can also create a dummy constructor as mentioned in following example:
class A:
def __init__(self):
self.a=10
def dummy_constructor(self):
temp = A()
temp.a = (self.a + 20 - 5 )*100/10
return temp
x=A()
y=x.dummy_constructor()
print(y.a) #250
print(x.a) #10
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
I want to check that my function has no side-effects, or only side-effects affecting precise variables. Is there a function to check that it actually has no side-effects (or side-effects on only certain variables)?
If not, how can I go about writing my own as follows:
My idea would be something like this, initialising, calling the function under test, and then calling the final method:
class test_side_effects(parents_scope, exclude_variables=[]):
def __init__():
for variable_name, variable_initial in parents_scope.items():
if variable_name not in exclude_variables:
setattr(self, "test_"+variable_name, variable_initial)
def final(self, final_parents_scope):
for variable_name, variable_final in final_parents_scope.items():
if variable_name[:5] is "test_" and variable_name not in exclude_variables:
assert getattr(self, "test_"+variable_name) is variable_final, "Unexpected side effect of %s from %s to %s" % (variable_name, variable_initial, variable_final)
#here parents_scope should be inputted as dict(globals(),**locals())
I'm unsure if this is precisely the dictionary I want...
Finally, should I be doing this? If not, why not?
I'm not familiar with the nested function testing library that you might be writing a test with, but it seems like you should really be using classes here (i.e. TestCase in many frameworks).
If your question then, is relating to getting the parent variables in your TestCase, you could get the __dict__ (It wasn't clear to me what the "Parent" variables you were referring to.
UPDATE: #hayden posted a gist to show the use of parent variables:
def f():
a = 2
b = 1
def g():
#a = 3
b = 2
c = 1
print dict(globals(), **locals()) #prints a=1, but we want a=2 (from f)
g()
a = 1
f()
If this is converted to a dictionary, then the problem is solvable with:
class f(object): # could be unittest TestCase
def setUp(self, a=2, b=1):
self.a = a
self.b = b
def g(self):
#a = 3
b = 2
c = 1
full_scope = globals().copy()
full_scope.update(self.__dict__)
full_scope.update(locals())
full_scope.pop('full_scope')
print full_scope # print a = 1
my_test = f()
my_test.setUp(a=1)
my_test.g()
You are right to look for a tool which has already implemented this. I am hopeful that somebody else will have an already implemented solution.
Lets suppose this example: Two siblings classes where one loads the other class as a new attribute and then i wish to use this attribute from the main class inside the sibling.
a = 2
class AN(object):
def __init__(self,a):
self.aplus = a + 2
self.BECls = BE(a)
class BE(object):
def __init__(self,a):
print a
def get_aplus(self):
????
c = AN(a)
and i'd like to do:
c.BECls.get_aplus()
and this shall return something like self.self.aplus (metaphorically), that would be 4
Resuming: get aplus attribute from AN inside BE class, without declaring as arguments, but doing a "Reverse introspection", if it possible, considering the 'a' variable must be already loaded trough AN.
Sorry if I not made myself clear but I've tried to simplify what is happening with my real code.
I guess the problem may be the technique i'm using on the classes. But not sure what or how make it better.
Thanks
OP's question:
get aplus attribute from AN inside BE class, without declaring as
arguments, but doing a "Reverse introspection", if it possible,
considering the 'a' variable must be already loaded trough AN.
The closest thing we have to "reverse introspection" is a search through gc.getreferrers().
That said, it would be better to simply make the relationship explicit
class AN(object):
def __init__(self,a):
self.aplus = a + 2
self.BECls = BE(self, a)
class BE(object):
def __init__(self, an_obj, a):
self.an_obj = an_obj
print a
def get_aplus(self):
return self.an_obj.aplus
if __name__ == '__main__':
a = 2
c = AN(a)
print c.BECls.get_aplus() # this returns 4