I created the following example to understand the instances in python
import time;
class test:
mytime = time.time();
def __init__(self):
#self.mytime = time.time();
time.sleep(1);
pass
from test import test
test1 = test()
test2 = test()
print test1.mytime
print test2.mytime
test1.mytime = 12
print test1.mytime
print test2.mytime
in this case the output id the following:
1347876794.72
1347876794.72
12
1347876794.72
I expected that the test2.mytime is bigger with 1 second than the test1.mytime. Why doesn't created a copy about the mytime in each instance?
Let's look at those lines:
class test:
mytime = time.time();
Here you set class member value, which is calculated once when class definition is executed, so time.time() is calculated once when module that contains class test is loaded.
Every instance of the class test will receive that precalculated value and you must override that value (e.g. in __init__ method), accessing it via self (which is a special argument that stores reference to an instance), thus setting instance member value.
the mytime = time.time() is executed when the class is defined(when the interpreter runs the class-definition-code, and this will be run only once, so all instances will get the same mytime.
if you want different mytime in different instances, you have to use the self's one, and access it with instance name rather than class name.
The reason the value never changes is because it is a class variable meaning when the class is defined and evaluated but not when instances are made then the value is set.
If you want the value to change make it set inside the initialiser
The mytime variable is first created as a class variable and not an instance variable.
Python tries to locate a name on an instance first and if it is not found it will lookup the name on the class. You can query the namespace of any object (including) classes by looking at the object's __dict__, which is a dictionary containing the instance variables.
As soon as you set test1.mytime = 12, you created a new name in that object's __dict__, which from then on shadowed the class variable with the same name.
let's uncomment "self.mytime = time.time()" line from your code:
class test:
mytime = time.time();
def __init__(self):
self.newtime = time.time();
time.sleep(1);
#pass - no use of pass here
test1 = test()
test2 = test()
print test1.mytime
o/p: 1347883057.638443
print test2.mytime
o/p: 1347883057.638443
In this case, "mytime" variable is like static class member. and all instances of test() class (i.e: test1 and test2) will share same value of class attributes.
print test1.newtime
o/p: 1347883063.421356
print test2.newtime
o/p: 1347883068.7103591
whereas, value of instance variable. will be different for each instance of class.
therefore, to get different timing for each instance. you need to declare instance variable using "self" in "init" method.
self = instance as a first parameter in class method
init = default constructor method in python for defined class
Hope, it will help.
Related
my question may sound a bit weird. In JS we can put an object on another one, how does it work in Python? what is the name of this functionality?
Example:
class A:
def __init__(self):
print('I am A')
class B:
def __init__(self):
print('I am B')
def i_am_a_function(x):
print('I am function')
print(x)
# What if I create a method using dot:
A.holder_for_b = B
# OR:
A.some_method = i_am_a_function
########
print(A.holder_for_b)
print(A.some_method('foo'))
result:
<class '__main__.B'>
I am function
foo
None
and as a final question, what is that "None" ?
I think you mean:
class A:
def __init__(self):
print('I am A')
class B:
def __init__(self):
print('I am B')
def i_am_a_function(x):
print('I am function')
print(x)
a = A()
b = B()
# What if I create a method using dot:
a.holder_for_b = B
# OR:
a.some_method = i_am_a_function
########
print(a.holder_for_b)
print(a.some_method('foo'))
## outputs:
I am A
I am B
<class '__main__.B'>
I am function
foo
None
So it seems that you can assign a function to an object. This is called in Python "monkey patching".
But the disadvantage of this is - I think:
It applies only to the object a - so you can't inherit it to another object
(different than in javascript I guess - prototype).
You can't interact with any other property or method in the class,
because you don't have self (in js this) available in that monkey-patched method.
(If I am wrong, please tell me.)
And it is bad style, because you should have in the class definition everything what you need. It would be hard to understand for anyone who wants to maintain the code.
Also the a.holder_for_b = B is unnecessary.
For what you would need a.holder_for_b? You can't anyway not inherit such a monkey-patched method to another object in Python.
Python's class definitions are lexical.
None
The None is the return value of the function call.
x = a.some_method('foo')
## I am function
## foo
x
## Nothing returned
x is None
## returns: True
print(x)
## None
As you can see: x returns nothing.
The None would not be visible if you would not have used print() around the call a.some_method('foo').
So the function is called - which prints I am a function and foo.
But the return value (None) gets returned from this call - and the print() prints it.
Putting an object to another
Do you mean "attaching"? This is very well possible in Python - by monkey patching.
a = A()
a.b = B()
Now, b is an attribut/property of the object a, which holds the object generated by B(). You could also just assign any already generated object to a in a similar way.
But this applies only to a. And in Python, you cannot generate another object based on a. So it is a little bit pointless in my view.
Perhaps more pythonic ways would be:
# everytime you generate an instance of the A class, generate an instance of B
# and attache it to newly generated instance of the A class as `b`:
class A:
def __init__(self):
print('I am A')
self.b = B()
# generate an instance of A, but attach as `b` property an existing object:
class A:
def __init__(self, obj):
print('I am A')
self.b = obj
b = B()
# ...
a = A(b)
# a.b is then identical to the generated `b` - it is a reference to it.
# So everything to do to it will be done to `b` too!
# This can be very confusing and create bugs.
a.b.my_new_property = 1
a.b.my_new_property ## 1
b.my_new_property ## 1
But I think your problem is that you are trying to apply JavaScript's prototypical OOP system habits to Python. In Python, you should better define everything in your class definitions, give other objects or classes as arguments to the constructor methods (__init__ or __new__).
And if you want to modify class definitions in a re-usable manner, probably use decorators or decorator classes. Or design patterns.
A class defines a namespace. A def creates a function object and assigns it to a variable in the active namespace. If that def is in the class namespace (one indentation in from the class definition), the variable is assigned to the class namespace. In your example, both __init__ functions are assigned to variables called "__init__" in the classes. i_am_a_function is not in a class namespace so it is assigned to the module ("global") namespace.
Normally, accessing a variable in a class namespace is just a name lookup like any other variable.
print(A.holder_for_b)
simply looked up the object in A.holder_for_b, which is a class object. You could add
print(A.holder_for_b())
and get an instance of that class. Similarly A.some_method is just looking up the variable on A. When you call it, you are just calling a function. You saw the print in the function itself and its None return value.
But python does something different if you reference a variable off of a class instance object (as opposed to the class object itself). If you try calling a variable (and it is a function object), python will convert that function object into a method and will automatically add a reference to the the instance as a so-called "self" object.
a = A()
print(a)
print(a.some_method())
prints
I am A
<__main__.A object at 0x7fb6c0ab61c0>
I am function
<__main__.A object at 0x7fb6c0ab61c0>
Here, since you call a variable of an instance object, its first parameter that you called "x" is now the instance object (the "self" parameter). Python didn't really care what you called that variable, its just the first in the parameter list.
I'm trying to learn about the basic construction of the python class. I have the following code which is completely running fine:
class Test1:
name = 'Choton'
age = 28
class Test2: # __init__ function executes whenever the class is called
def __init__(self):
self.name = 'Choton'
self.age = 28
print('Class Test2 is called and initialized...')
def main():
# Test1
print(f'Test1:')
print(f'Test1().name = {Test1().name}, Test1().age = {Test1().age}')
print(f'Test1.name = {Test1.name}, Test1.age = {Test1.age}\n')
# Test2
print(f'Test2:')
print(f'Test2().name = {Test2().name}, Test2().age = {Test2().age}')
# DOES NOT WORK
# print(f' name = {Test2.name}, age = {Test2.age}')
if __name__ == '__main__':
main()
I know that the __init__ function always runs whenever a class is initialized. Here the Test1 class do not have any __init__ function and both Test1.name and Test1().name works fine. But whenever I am calling the name using the __init__ function in Test2, the Test2.name does not work anymore. It says the following error if I uncomment that line: AttributeError: type object 'Test2' has no attribute 'name'.
What is the difference in here? Why both syntax work for one class and not for the other? I am a bit confused about it. Is there any syntactic sugar in here or any generalization that I am missing?
In Test1 you are defining class variables, which are shared between all objects, and can be accessed by using the class only (Test1.name) as well as from the instance (Test1().name).
Defining self.name in Test2.__init__ makes it an instance variable, which is only available on a specific instance of the class, e.g. new object created by Test2()
Took me a long time to get my head around classes, I'm still not there. The init function isn't needed in every class, one thing it's used for is to allocate different values to the class attributes.
For info,
Test1 is the class.
Test1() is an instance of the class.
Both can be assigned. So you could say:
MyClassInstanceA = Test1()
MyClassInstanceB = Test1()
... These two are different items because they are both instances of the Test1 class, each instance is unique.
Or you could say
MyClassA = Test1
MyClassB = Test1
... These two are the same thing as they are both allocated Test1, not Test1()....
name and age are attributes. In the case of Test1 they are "class attributes". That is, the exist at the class level. They can be accessed via the class or an instance of the class. Remember Test1 is the class Test1() is an instance of the class.
The subtle difference between Test1() and Test1 is what is causing the error.
To further explain. In the Test1 class, the two attributes name and age exist in the class, before we create an instance of the class. If we do create any instances name and age attributes will be the same across all instances. But the important thing here is we don't have to create an instance of the class to access them. That's why Test1.name works....
On the other hand, in Test2 class. The attributes are only created when the class is initiated (this is what the init function is doing). They don't exist until then. So, when we want to access them you need to access them via an instance of the class Test2().name....
MyClassC = Test2
... Still no instance of the class so name or age doesn't exist
MyClassInstanceD = Test2()
... Now we have an instance of the class so name and age exists and it is accessed via that class which is called MyClassInstanceD...
MyClassInstanceD.name = 'Choton'
But as name and age only exist in the instance we can still not call
Test2.name
as this still doesn't exist and never will unless you modify the Test2 class...
I am new in python i read about Instance variable:
A variable that is defined inside a method and belongs only to the
current instance of a class.
So i test it:
Consider this code:
class test:
count=0
def __init__(self):
test.count += 1
I have a class that add count after Instantiation.
I run this:
t1=test()
t1.count=100
and then I create new instance:
t2=test()
t2.count # 2
then create another instance:
t3=test()
t3.count # 3
t2.count # 3
and then :
t1.count # I get 100
My question is why t2 and t3 was update but if change value of instance variable of specific instance the instance 's instance variable was not update?
In t2 and t3, since you haven't defined an instance variable count, referring to, e.g., t2.count looks up the name in the class scope and evaluates to the class variable test.count.
In t1, you've created a completely different instance variable count that just happens to have the same name as the class variable. t1.count therefore returns this instance variable.
Because instance attributes shadow class attributes, but they are independent.
When you try to access t2.count, there is no instance attribute (t2.__dict__ does not have a count key), so Python next looks at type(t2) to see if it can find the attribute there. The class does have such an attribute, so test.count is returned.
t1.count on the other hand finds the instance attribute and returns that. test.count is never considered.
I was wondering what was the difference between the Foo.var= user input and self.var= userinput in the 2 classes.
class foo():
var=None
def __init__(self,userinput):
foo.var=userinput
class bar():
var=None
def __init__(self,userinput):
self.var=userinput
foo refers to the class, self refers to the object.
Class members are a property of the class (and thus are shared between all objects of that class), while instance members are a property of the specific object, so a change to an instance member affects only the given object.
When you operate on an object, the members it has are a merge of the class members and the instance members. When two members with the same name are defined, the instance members have the priority.
Thus:
bar sets an instance variable; that change has effect only on the current instance, so if you do:
b=bar(10)
c=bar(20)
you'll see that c.var is 20 and b.var is 10; nothing strange here;
foo sets a class variable, which is common to all the instances; so, if you do:
f=foo(10)
g=foo(20)
you'll see that both f.var and g.var will be 20, because they both actually refer to foo.var, that was last set to 20 in g's constructor;
on the other hand, instance variables shadow class variables; so, if you do
f=foo(10)
g=foo(20)
f.var=30
you'll have g.var==foo.var==20, but f.var==30, since now f.var refers to the instance variable f.var; but, if you do
del f.var
now the instance (f's) attribute var no longer exists, and thus f.var refers again to the class attribute var (thus f.var==g.var==foo.var==20).
Long story short: normally you'll want to use self.var (i.e. instance members); classname.var is only for sharing stuff between all instances of a given class.
I'd like to point to an existing post which explains the difference perfectly in my opinion.
Python: Difference between class and instance attributes
Yes,
In the first instance you are setting the variable for all instances of foo this is because it is a class variable.
In the second case you are only setting the variable for that instance of foo.
For Example:
class pie():
def __init__(self, j):
pie.var = "pies" + str(j)
print (self.var)
def __str__(self):
return self.var
a = pie(1)
b = pie(2)
print (a)
print (b)
Why are constructors indeed called "Constructors"? What is their purpose and how are they different from methods in a class?
Also, can there be more that one __init__ in a class? I tried the following, can someone please explain the result?
>>> class test:
def __init__(self):
print "init 1"
def __init__(self):
print "init 2"
>>> s=test()
init 2
Finally, is __init__ an operator overloader?
There is no function overloading in Python, meaning that you can't have multiple functions with the same name but different arguments.
In your code example, you're not overloading __init__(). What happens is that the second definition rebinds the name __init__ to the new method, rendering the first method inaccessible.
As to your general question about constructors, Wikipedia is a good starting point. For Python-specific stuff, I highly recommend the Python docs.
Why are constructors indeed called "Constructors" ?
The constructor (named __new__) creates and returns a new instance of the class. So the C.__new__ class method is the constructor for the class C.
The C.__init__ instance method is called on a specific instance, after it is created, to initialise it before being passed back to the caller. So that method is the initialiser for new instances of C.
How are they different from methods in a class?
As stated in the official documentation __init__ is called after the instance is created. Other methods do not receive this treatment.
What is their purpose?
The purpose of the constructor C.__new__ is to define custom behaviour during construction of a new C instance.
The purpose of the initialiser C.__init__ is to define custom initialisation of each instance of C after it is created.
For example Python allows you to do:
class Test(object):
pass
t = Test()
t.x = 10 # here you're building your object t
print t.x
But if you want every instance of Test to have an attribute x equal to 10, you can put that code inside __init__:
class Test(object):
def __init__(self):
self.x = 10
t = Test()
print t.x
Every instance method (a method called on a specific instance of a class) receives the instance as its first argument. That argument is conventionally named self.
Class methods, such as the constructor __new__, instead receive the class as their first argument.
Now, if you want custom values for the x attribute all you have to do is pass that value as argument to __init__:
class Test(object):
def __init__(self, x):
self.x = x
t = Test(10)
print t.x
z = Test(20)
print t.x
I hope this will help you clear some doubts, and since you've already received good answers to the other questions I will stop here :)
Classes are simply blueprints to create objects from. The constructor is some code that are run every time you create an object. Therefor it does'nt make sense to have two constructors. What happens is that the second over write the first.
What you typically use them for is create variables for that object like this:
>>> class testing:
... def __init__(self, init_value):
... self.some_value = init_value
So what you could do then is to create an object from this class like this:
>>> testobject = testing(5)
The testobject will then have an object called some_value that in this sample will be 5.
>>> testobject.some_value
5
But you don't need to set a value for each object like i did in my sample. You can also do like this:
>>> class testing:
... def __init__(self):
... self.some_value = 5
then the value of some_value will be 5 and you don't have to set it when you create the object.
>>> testobject = testing()
>>> testobject.some_value
5
the >>> and ... in my sample is not what you write. It's how it would look in pyshell...
coonstructors are called automatically when you create a new object, thereby "constructing" the object. The reason you can have more than one init is because names are just references in python, and you are allowed to change what each variable references whenever you want (hence dynamic typing)
def func(): #now func refers to an empty funcion
pass
...
func=5 #now func refers to the number 5
def func():
print "something" #now func refers to a different function
in your class definition, it just keeps the later one
There is no notion of method overloading in Python. But you can achieve a similar effect by specifying optional and keyword arguments