+ 6
Can you please explain the output of this code?
a, b = 0, 0 class myClass(): a, b = 1, 1 def__init__(self): self.a = 2 self.b = 2 def__str__(self): return str(a + b) m = myClass() print(m) What is the difference being 0, 1 and 2? Answer is 0
12 Answers
+ 5
a,b = 0,0
-here “a” and “b” are global variables (global - means that we can use them simply as you usually use every variable).
a,b = 1,1
-here “a” and “b” are CLASS ATRIBUTES. That means that each object (member) of the class myClass has value of self.a and self.b equal to “1”, EXCEPT of those objects (members) that are provided with extra parameter while being initilized (for example we usually see this: a=myClass(15) So 15 will be self.a). BUT in your code “__init__” method assigns default “2” value to self.a and self.b attributes.
So when you see m=myClass(), we know that m.a==2 and m.b==2.
But when you see print(m), to be printed “m” need to call __str__ method, that returns str(a+b). As we already know from the begining “a” and “b” are global variables, that is why the answer is 0+0==0!
If there is return str(self.a+self.b) the anwer would be 2+2==4.
As i understand class attributes in this example (a,b =1,1) can only be accesed by myClass.a and myClass.b.
Waiting for HonFu’s explanation=)
+ 6
Mikhail, well explained. :)
I'll just add a little 'bonus' info':
When an instance accesses an attribute using that 'self' argument (which is obviously the instance itself), it first looks within its own attributes: Is that atty in there?
If it should not be in there, it will try to see if it's in the class it has inherited from - all the way up to the base class. If it doesn't find the attribute anywhere, you'll get an error.
So when the instance has that attribute itself, for example added to it by the init method, it will stop looking right there, and you never get to see the class attribute.
If you want to access that class attribute anyway, instead of...
myClass.a
... you can also write:
self.__class__.a
(The instance knows its 'mother'.)
Yeah, and if you forget to write 'self' altogether (I seem to like to do that 🙄), the method will just read out into the global scope.
+ 4
__str__ is used to return the string representation of the object. This method is called when print() or str() function is invoked on an object.
In this example it returns sum of variables a and b. They both are zeros, so result of the function is zero.
(To sum members a,b of myClass self should be used , like
str(self.a + self.b).
In this case result would be 4)
When print(m) is called, Python calls the __str__ method to get string representation of the object m which is an instance of class myClass.
__str__ retuns "0", so result is "0".
+ 4
Look at this 'joke' to see:
https://code.sololearn.com/cJp9j0Db5sgT/?ref=app
+ 3
HonFu,
what will happen if we add
“del (m.a)” at the end of the code?
What will “print(m.a)” give us after that??
+ 3
So it will look at class attribute, i.e. m.a will be equal to 1?
+ 3
It will look through the chain of inheritance one by one, and if it finds something, it takes that.
So if originally an instance or class on that way had the attribute (and would have been the stopping point) but then you deleted it, the search will just go on with the next step.
That's why cutting the allowance will not bleed out the spoiled child, but it will just continue to look for money in daddy's purse. ;-)
+ 3
HonFu 🤣🤣🤣👍👍👍
+ 2
The difference being 0, 1 and 2 is next;
line #1:
a, b = 0, 0
a, b are global variables, you can access them inside or outside functions
line #3
a, b = 1, 1
a, b are members of class myClass which have default values = 1, you can access them inside class through self (like self.a=2). Every object of class myClass will have its own a,b after instantiation. You can access them outside class using dot:
print(m.a) # will prints 2
lines #5, #6
self.a = 2
self.b = 2
it is initalization of members a,b inside constructor. Default values of a and b are overwritten with 2.
__init__ is a constructor of class, it is called when an object is created:
m = myClass() # will call __init__ of myClass
whithout constructor a,b would have default values (1).
+ 2
may be this code will help you better understand:
a, b = "global", "global"
class myClass():
a, b = "default", "default"
def __init__(self):
self.a = "from constructor"
m = myClass()
m1 = myClass();
print("Global a.b:")
print("a={}, b={}".format(a, b))
print("\nObjects m and m1:")
print("m.a={}, m.b={}, m1.a={}, m1.b={}".format(m.a, m.b, m1.a, m1.b))
m.a = "changed outside"
print("\nObjects m and m1 after changing m.a:")
print("m.a={}, m.b={}, m1.a={}, m1.b={}".format(m.a, m.b, m1.a, m1.b))
output will be:
Global a.b:
a=global, b=global
Objects m and m1:
m.a=from constructor, m.b=default, m1.a=from constructor, m1.b=default
Objects m and m1 after changing m.a:
m.a=changed outside, m.b=default, m1.a=from constructor, m1.b=default
0
Great