Is there a way in Python, that i can use the variable value for creation of Class instance
class Test(object):
def __init__(self, object):
self.name = object
print "Created Object :",self.name
a1 = Test('a1')
print a1.name
b2 = 'a2'
b2 = Test(b2)
print a2.name
In this example, i want the class instance name should be 'a1' and 'a2' respectively. I cannot directly use the value 'a2' as it is computed from some other process, but the class instance name must match it such that it can be accessed.
In the above example, it gives error :
Created Object : a1
a1
Created Object : a2
Traceback (most recent call last):
File "D:\a\h", line 12, in <module>
print a2.name
NameError: name 'a2' is not defined
Any time you want to dynamically create variable names, you need to stop and tell yourself that a dictionary is a better way to go. If you want the class instance to be available anywhere (which is also not the best idea), but here's how you can do that:
class Test(object):
instance_dict={}
def __init__(self,name):
self.name=name
self.instance_dict[name] = self
Now you can use this class:
a1 = Test("a1")
print a1 is Test.instance_dict["a1"] #True
b1 = Test("a2")
print b1 is Test.instance_dict["a2"] #True
In other words, the instance_dict class attribute keeps a handle on the most recently created instance with a particular name so you have a handle on the instances anywhere that Test is available.
However, I do not recommend this type of design. The downsides here are the same as the downsides with using global variables. It will probably become difficult to maintain, hard to tell what exactly is going on, etc. simply because the flow of data through your program is not well ordered.
The closest thing to what you are looking for is to store all your instances in a dictionary:
class Test(object):
def __init__(self, n):
self.name = n
print "Created Object :",self.name
d = {}
d['a1'] = Test('a1')
print d['a1'].name
b2 = 'a2'
d[b2] = Test(b2)
print d['a2'].name
There is no connection between the name of a variable that references an object and the object itself.
Try print b2.name instead.
Note: The name name doesn't mean anything special to Python. "Giving your class a name" means nothing to Python, it just executes the code that you write. "Giving your class a name" means something to you but Python can't and won't read your mind :-)
So setting the name of the instance referenced by b2 to a2 doesn't magically create a reference a2.
This introduction to variable names might help: Learn to Program Using Python: Variables and Identifiers
In a nutshell, if you write
a = 'x'
Python
Creates a string instance
Assigns a value to that string instance (the text x)
Assigns a reference to this new string instance to the alias a
If you then write:
b = a
there is still only a single string instance in memory. You only created a second alias b which references the same string instance as a.
Related
While learning about how classes work in Python I came across a class definition example which behaved kind of strangely in my eyes.
The purpose of the example was to demonstrate how the behaviour of a static variable can be achieved in Python. The example was written as follows:
class MemberCounter:
members = 0
def init(self):
MemberCounter.members += 1
m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()
after setting up the class and creating the objects, I printed the values of the 'members' attribute. These were the results:
MemberCounter.members = 2
m1.members = 2
m2.members = 2
And that's when I got confused. While I was expecting for 'MemberCounter.members = 2' the two other results made no sense to me - why would both of 'm1' and 'm2' objects' 'members' value be equal to 2? I thought that both of the values should have been 0 - if the only attribute that was chaged is the 'members' attribute which was attached to the MemberCounter class why would it cause any change to the own unique 'members' value of each of the class' objects. It looks like the fact that the 'members' attribute is addresed like 'MemberCounter.members += 1' in the init() function of each object, completely overrides the unique values which m1.members and m2.members refer to and redirects their pointers to the MemberCounter.members value making all the three pointers point at the same value
==> m1.members = m2.members = MemberCounter.members.
Moreover, I have tried defining the class in an opossite way (Increasing self.members instead of MemberCounter.members):
class MemberCounter:
members = 0
def init(self):
self.members += 1
m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()
This definition yielded logical results (which got me curious about the above mentioned strange behaviour even more):
MemberCounter.members = 0
m1.members = 1
m2.members = 1
In short, I was curious about why the first class definition behaves in such a strange way? Why the mere 'MemberCounter.members += 1' statement completely erased 'm1.members' and 'm2.members' own unique value and made it equal to the MemberCounter.members value.
I hope I was able to clearly present my problem and I will be extremly happy to get an insight about this strange behaviour :)
That you can read a static attribute with instance.attribute notation as alternative to the more natural class.attribute notation, is an intended feature in Python.
From the documentation:
Both static data and static methods (in the sense of C++ or Java) are supported in Python.
For static data, simply define a class attribute. To assign a new
value to the attribute, you have to explicitly use the class name in
the assignment:
class C:
count = 0 # number of times C.__init__ called
def __init__(self):
C.count = C.count + 1
def getcount(self):
return C.count # or return self.count
c.count also refers to C.count for any c such that
isinstance(c, C) holds, unless overridden by c itself or by some
class on the base-class search path from c.__class__ back to C.
Caution: within a method of C, an assignment like self.count = 42
creates a new and unrelated instance named “count” in self’s own dict.
Rebinding of a class-static data name must always specify the class
whether inside a method or not:
C.count = 314
The paragraph just below the first code block explains your doubts. The "Caution" paragraph explains what you found logical.
All the code I have seen to create an instance of an object has used a variable and the use of the instance of an object is short lived, like a game. A new game replaces that instance and there is no need to recall previous objects. Or I have seen manually produced instances not using a catchall variable. Like c1 and c2 so on and so forth.
class Child:
def __init__ (self, name,):
self.name = name
child = Child(name)
I have created multiple instances of my object and have attached them inside another class by appending them to a list. However if I were to change an attribute of an instance, I don't know how to call it with a generic variable 'child' used to instantiate. I can do this when I have used c1 or c2 to instantiate : like c1.name. But I would have to manually write c1 or c2. Versus when I call child.name I only return the last child that was created.
Does anyone have an a suggestion?
As you mentioned, you can use a list to store the instances of the object you create. For example, building on the code you have, you could do something like:
my_objects = []
for name in ('one', 'two', 'three', 'four'):
child = Child(name)
my_objects.append(child)
Then, if you wanted to recall the second object you created, you could acess it from the list:
child = my_objects[1] # this is the second one you created
print(child.name) # this prints 'two'
child.name = 'second' # now the name is second!
Alternatively you could directly call my_objects[1].name = 'second'.
I've just get to know about Class and User-Defined-Function in Python and currently practicing with them.
Sometimes I got really confused whether an inputted variable or instance attribute is directly used or been copied as a local variable that only works during the call of function.
For example:
class test1(object):
def __init__(self, a):
self.a = a
class test2(object):
def __init__(self, test):
self.a = test.a
self.add_d()
def add_d(self):
self.a += 'd'
print self.a
class test3(object):
def __init__(self, test):
self.fc = test
self.add_d()
def add_d(self):
self.fc.a += 'd'
print self.fc.a
And:
In [36]: t = test1('abc')
In [37]: test2(t)
abcd
Out[37]: <__main__.test2 at 0xce5bcf98>
In [38]: t.a
Out[38]: 'abc'
It didn't change attribute "a" of instance "t" from class test1.
In [39]: test3(t)
abcd
Out[39]: <__main__.test3 at 0xfc3c9e8>
In [40]: t.a
Out[40]: 'abcd'
It changed attribute "a" of instance "t" from class test1.
Usually, I used functions for several scenario:
Aim to alter (mutate) the input variables from calling a function.
The return value is the only thing desired from the function call, and inputted variables should be unchanged.
Passing an Axes of matplotlib and arrange plotting commands in the function. (This would always work, never went wrong.)
Things would be pretty troublesome if I made unwanted changes to raw data and vice versa. So what is the basic concept here? Also, is there any habits that we should develop to prevent this kind of mistake?
I think that you are asking why was the test1 instance modified in the second example but not modified in the first?
In the first one after:
self.a = test.a
self.a refers to test.a which is the same immutable string object. Now when:
self.a += 'd'
executes it rebinds the value of the expression self.a + d to self.a, i.e. a new string object is created. Because strings are immutable the original can not be altered, so a new one must be created. At this point the attribute a in the test2 object refers to a different object than the a attribute in the test1 object, which remains unchanged.
In the second example after
self.fc = test
self.fc refers to the object test which is the same object that the variable t refers to. In terms of variable references this is the same as the first case, however, the difference is that this object is mutable so when
self.fc.a += 'd'
executes a new string is created and bound to the a attribute of the object - but self.fc still refers to the same object. Hence t.a is changed.
I've tried to explain this in terms of your example. The crucial point is that Python variables refer to objects, and there can be multiple references to the same object. Changes to the object can be made via any of the referring variables, and that change will be visible regardless of which variable is used to view it. Copies of objects are not made during assignment, however, the reference can be changed if a new object is created in order to preserve the immutability of certain objects.
I recommend that you give this a read Facts and myths about Python names and values.
I am fairly new to Python and OOP. Suppose I have two classes, Base1 and Base2. Suppose also that Base1 has computed some values a1, b1 and that Base2 has a method that multiplies two values. My question is, what is the correct way of passing a1 and b1 of Base1 to multiply in Base2?
One way to do this by defining a derived class, Derived as follows:
class Base1:
def __init__(self, x1 , y1):
# perform some computation on x1 and y1
# store result in a1 and b1
self.a1=x1
self.b1=y1
class Base2:
def __init__(self, x2 , y2):
self.a2=x2
self.b2=y2
self.c2=self.multiply(self.a1,self.b1) # using a1 and b1 of Base1
def multiply(self, p,q):
return p*q
class Derived(Base1,Base2):
def __init__(self):
self.describe='Derived Class'
Base1.__init__(self,3,4)
Base2.__init__(self,5,6)
Then:
f=Derived()
f.c2=12
However, in a more complex situation, it is easy to lose track of where self.a1, self.b1 came from. It is also not obvious to me why the two base classes can access the attributes and the methods of each other in this way?
Edit: This is Python 2.7.10.
In Python 2 always inherit from object. Otherwise you get old-style classes which should not use:
class Base1(object):
def __init__(self, x1 , y1):
# perform some computation on x1 and y1
# store result in a1 and b1
self.a1 = x1
self.b1 = y1
class Base2(object):
def __init__(self, x2 , y2):
self.a2 = x2
self.b2 = y2
self.c2 = self.multiply(self.a1, self.b1) # using a1 and b1 of Base1
def multiply(self, p,q):
return p*q
class Derived(Base1, Base2):
def __init__(self):
self.describe='Derived Class'
Base1.__init__(self, 3, 4)
Base2.__init__(self, 5, 6)
Python looks for methods using the method resolution order (mro). You can find out the current order:
>>> Derived.mro()
[__main__.Derived, __main__.Base1, __main__.Base2, object]
That means Python looks for a method multiply() in the class Derived first. If it finds it there, it will use it. Otherwise it keeps searching using the mro until it finds it. Try changing the order of Base1 and Base2 in Derived(Base1,Base2) and check how this effects the mro:
class Derived2(Base2, Base1):
pass
>>> Derived2.mro()
[__main__.Derived2, __main__.Base2, __main__.Base1, object]
The self always refers to the instance. In this case f (f = Derived()). It does not matter how f gets its attributes. The assignment self.x = something can happen in any method of any of the classes involved.
TL;DR
Python is dynamic. It doesn't check if attributes are present until the actual line of code that tries to access them. So your code happens to work. Just because you can do this, doesn't mean you should, though. Python depends on you to make good decisions in organizing your code rather than trying to protect you from doing dumb things; we're all adults here.
Why you can access variables
The reason really boils down to the fact that Python is a dynamic language. No types are assigned to variables, so Python doesn't know ahead of time what to expect in that variable. Alongside that design decision, Python doesn't actually check for the existence of an attribute until it actually tries to access the attribute.
Let's modify Base2 a little bit to get some clarity. First, make Base1 and Base2 inherit from object. (That's necessary so we can tell what types we're actually dealing with.) Then add the following prints to Base2:
class Base2(object):
def __init__(self, x2 , y2):
print type(self)
print id(self)
self.a2=x2
self.b2=y2
self.c2=self.multiply(self.a1,self.b1) # using a1 and b1 of Base1
def multiply(self, p,q):
return p*q
Now let's try it out:
>>> d = Derived()
<class '__main__.Derived'>
42223600
>>> print id(d)
42223600
So we can see that even in Base2's initializer, Python knows that self contains a Derived instance. Because Python uses duck typing, it doesn't check ahead of time whether self has a1 or b1 attributes; it just tries to access them. If they are there, it works. If they are not, it throws an error. You can see this by instantiating an instance of Base2 directly:
>>> Base2(1, 2)
<class '__main__.Base2'>
41403888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __init__
AttributeError: 'Base2' object has no attribute 'a1'
Note that even with the error, it still executes the print statements before trying to access a1. Python doesn't check that the attribute is there until the line of code is executed.
We can get even crazier and add attributes to objects as the code runs:
>>> b = Base1(1,2)
>>> b.a1
1
>>> b.notyet
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Base1' object has no attribute 'notyet'
>>> b.notyet = 'adding an attribute'
>>> b.notyet
'adding an attribute'
How you should organize this code
Base2 should not try to access those variables without inheriting from Base1. Even though it's possible to do this if you only ever instantiate instances of Derived, you should assume that someone else might use Base2 directly or create a different class that inherits from Base2 and not Base1. In other words, you should just ignore that this is possible. A lot of things are like that in Python. It doesn't restrict you from doing them, but you shouldn't do them because they will confuse you or other people or cause problems later. Python is known for not trying to restrict functionality and depending on you, the developer, to use the language wisely. The community has a catchphrase for that approach: we're all adults here.
I'm going to assume that Base2 is primarily intended to be just a mix-in to provide the multiply method. In that case, we should define c2 on the subclass, Derived, since it will have access to both multiply and the attributes a1 and b1.
For a purely derived value, you should use a property:
class Derived(Base1,Base2):
def __init__(self):
self.describe='Derived Class'
Base1.__init__(self,3,4)
Base2.__init__(self,5,6)
#property
def c2(self):
return self.multiply(self.a1,self.b1) # using a1 and b1 of Base1
This prevents callers from changing the value (unless you explicitly create a setter) and avoids the issue of tracking where it came from. It will always be computed on the fly, even though using it looks like just using a normal attribute:
x = Derived()
print x.c2
This would give 12 as expected.
You can just provide a method multiply in the base class which assumes that a1 and b1 has been defined in the base class.
So the code will be like
class Base1(object):
def __init__(self,a1,b1):
self.a1 = a1
self.b1 = b1
class Base2(Base1):
def multiply():
return self.a1*self.b1
Here as you havent provided a __init__ for base2 it will use the init method of base1 which takes in parameters as a1 and a2
so now
base = Base2(5,4)
print(base.multiply())
I'm trying to use a variable in other python modules, like this:
In a.py:
class Names:
def userNames(self):
self.name = 'Richard'
In z.py:
import a
d = a.Names.name
print d
However this doesn't recognise the variable name and the following error is received:
AttributeError: type object 'Names' has no attribute 'name'
Thanks
There are lots of different scopes a variable can be bound to, which is what you seem to be confused about. Here are a few:
# a.py
a = 1 # (1) is module scope
class A:
a = 2 # (2) is class scope
def __init__(self, a=3): # (3) is function scope
self.a = a # (4) self.a is object scope
def same_as_class(self):
return self.a == A.a # compare object- and class-scope variables
def same_as_module(self):
return self.a == a # compare object- and module-scope variables
Now see how these different variables (I only called them all a to make the point, please don't do this for real) are named, and how they all have different values:
>>> import a
>>> a.a
1 # module scope (1)
>>> a.A.a
2 # class scope (2)
>>> obj1 = a.A() # note the argument defaults to 3 (3)
>>> obj1.a # and this value is bound to the object-scope variable (4)
3
>>> obj.same_as_class()
False # compare the object and class values (3 != 2)
>>> obj2 = a.A(2) # now create a new object, giving an explicit value for (3)
>>> obj2.same_as_class()
True
Note we can also change any of these values:
>>> obj1.same_as_module()
False
>>> obj1.a = 1
>>> obj1.same_as_module()
True
For reference, your z.py above should probably look like:
import a
n = a.Names()
d.userNames()
d = n.name
print d
because a.Name is a class, but you're trying to refer to an object-scope variable. An object is an instance of a class: I've called my instance n. Now I have an object, I can get at the object-scope variable. This is equivalent to Goranek's answer.
In terms of my previous example, you were trying to access obj1.a without having an obj1 or anything like it. I'm not really sure how to make this clearer, without turning this into an introductory essay on OO and Python's type system.
"I've checked again and it's because I'm importing from is a Tornado Framework and the variable is within a class."
Accordingly, your problem is not the one shown in your question.
If you actually want to access the variable of a class (and likely, you don't), then do this:
from othermodule import ClassName
print ClassName.var_i_want
You probably want to access the variable as held inside an instance:
from othermodule import ClassName, some_func
classnameinstance = some_func(blah)
print classnameinstance.var_i_want
Update Now that you have completely changed your question, here is the answer to your new question:
IN this code:
class Names:
def userNames(self):
name = 'Richard'
name is not a variable accessible outside of the activation of the method userNames. This is known as a local variable. You would create an instance variable by changing the code to:
def userNames(self):
self.name = 'Richard'
Then, if you have an instance in a variable called classnameinstance you can do:
print classnameinstance.name
This will only work if the variable has been already created on the instance, as by calling userNames.
You don't need to import the class itself if there is some other way to receive instances of the class.
file:a.py
class Names:
def userNames(self):
self.name = 'Richard'
file:z.py
import a
c = a.Names()
c.userNames()
what_you_want_is = c.name
Btw, this code makes no sense..but this is apparently what you want
Better a.py
class Names:
def userNames(self, name):
self.name = name
Better z.py
import a
c = a.Names()
c.userNames("Stephen or something")
what_you_want_is = c.name
# what_you_want_is is "Stephen or something"