What is classobject in python is it same as class name? - python

class Test:
def __init__(self):
print('Object reference:', id(self))
print('Class object reference', id(Test))
t = Test()
Object reference: 2170838573008
Class object reference: 2170806511808

It is not the same as class name. Everything is an object in Python. Classes are, and their instances, too. Even modules, and functions, just everything.

Class Name is not same as class object. When you create an instance of class that time you create an object for that class. In your case t is a Object of class Test.
Almost everything is object in python. So as your class is a type of object.
class Test:
def __init__(self):
print('Object reference:',id(self))
print('Class object reference',id(Test))
t = Test() // Here t is object of class Test.

when you use class keyword, you are actually creating an instance of type type. Classes are instances themselves.
class Test:
pass
print(isinstance(Test, type)) # True
print(type(Test)) # <class 'type'>
here, Test is just a label in your global namespace, which points to this instance you have created.
Now when you call your class, here Test, you are creating an instance of it. self inside your class, points to this object (instances of your class).

Related

How to get an existing class based on class name?

I have a class:
class Test():
pass
I know the class name is "Test". How can I get class Test? A class is an object of class. I would like to get the class object based on its name, the text "Test".
In my project I have many classes defined. I would like to instantiate a class based on its name (without using an if statement).
If the class is defined in the global namespace, you can do it this way:
class Test:
pass
test_class = globals()["Test"]
print(test_class) # -> <class '__main__.Test'>
I don't suggest following such a convention, as this is very bad practice. A class is not an object of class, it's just a class that has been defined. Any objects you define using that class will be an object of that class and have its own instance. Please don't use the same name for different classes, this is almost never maintainable and you should never do it this way.

Getting the name of a class which has a meta class

Suppose I define a class A with a meta class like this:
class Meta(type):
pass
class A(metaclass=Meta):
pass
Then, when I try to access the name of class A I get the name of the meta class:
A.__class__.__name__
# 'Meta'
However, shouldn't it give me A, my defined class?
Note: I tried to use A.__mro__[0].__name__ and it does give me A, but I am still confused why A.__class__ gives me the meta class name. Does anyone has an explanation of this?
The __class__ dunder reports:
the class to which a class instance belongs.
Quote from instance.__class__
The class A belongs to the class of it's metaclass - only instances of A belong to the class A itself.
a = A()
print(a.__class__.__name__) # 'A'
print(A.__class__.__name__) # 'Meta'
class P: pass
print(P.__class__.__name__) # type
print(P().__class__.__name__) # P
To get the name of the class itself simply use
A.__name__
if you really need it.
I am still a way to groke all of answer to What are metaclasses in Python? - maybe it helps you out.
A is already the class - its name is under A.__name__.
If you try A.__class__.__name__ you will get to the class of which A is instance (that is, its metaclass), name.
A.__mro__[0].__name__ will follow the "method resolution order" for the class A - the __mro__ object is a tuple with all the class hyerarchy that starts in the defined class itself and ends in object. So, A.__mro__[0] will always be A itself - and A.__mro__[0].__name__ is the same as A.__name__.
The __name__ and __qualname__ attributes are writable attributes: changing { __qualname__ after the class is created will change the default __repr__ for instances of that class, for example. Although they are in the language definition and "live" in slots in the class (not on it's dictionary), it is possible to create a __name__ property (I mean, the built-in property object, or any other descriptor) on the metaclass that will dynamically change the __name__ attribute of a class (but not __qualname__ - this must be an attribute of the class, and must be a string)

Best way to access class-method into instance method

class Test(object):
def __init__(self):
pass
def testmethod(self):
# instance method
self.task(10) # type-1 access class method
cls = self.__class__
cls.task(20) # type-2 access class method
#classmethod
def task(cls,val)
print(val)
I have two way to access class method into instance method.
self.task(10)
or
cls = self.__class__
cls.task(20)
My question is which one is the best and why??
If both ways are not same, then which one I use in which condition?
self.task(10) is definitely the best.
First, both will ultimately end in same operation for class instances:
__class__ is a special attribute that is guaranteed to exist for an class instance object and is is the class of the object (Ref: Python reference manual / Data model / The standard type hierarchy)
Class instances ...Special attributes: __dict__ is the attribute dictionary; __class__ is the instance’s class
calling a classmethod with a class instance object actually pass the class of the object to the method (Ref: same chapter of ref. manual):
...When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself
But the first is simpler and does not require usage of a special attribute.

Python class inheritance __init__

So, here's the problem..
if you do this:
class x(object):
def __init__(self):
pass
why would you explicitly call init in child class to access parent class attribute? (class y has class x attribute anyway.)
class y(x):
def __init__(self):
x.__init__(self)
Cheers.
Edit:
I read this article https://linuxmeerkat.wordpress.com/2015/04/28/why-you-should-use-super-in-python/, it says "In real life we tend to run the initializer for every parent class. This is simply because of how program designs tend to be. In our simple example a way to solve this is to explicitly call the initializer of A:" Could someone please explain?
The fact is that in python there is a clear distinction between class and instance attributes:
Attributes declared in the class body, outside any method, are class attributes, they are the same for each object of that class and are the ones that are inherited by the subclasses. Be aware of the fact that doing instance_obj.class_att = something doesn't change the value of the class attribute, but simply creates an instance attribute and hides the shared class attribute for that object.
Instance attributes are the ones that are declared with syntax instance_obj.att = something, they are not shared between instances and are the most similar thing to non-static attributes that you have in other programming languages and they are usually created in the init method.self is just a convention to indicate the instance object automatically passed to methods.
Here's an example:
class MyClass:
c = 1 #class attribute, the subclasses will inherit this
def __init__(self):
self.i = 1 #instance attribute
MyClass.c #access attribute c of class MyClass
MyClass.i #error! MyClass has no attribute i
x = MyClass() #calling __init__ creates instance attribute i for obj x
x.i #access instance attribute i of object x
x.c #access class attribute c of class MyClass
x.c = 2 #hide MyClass.c and create instance attribute c for obj x
x.c #access instance attribute c of obj x
So, to sum up, doing:
class y(x):
def __init__(self):
x.__init__(self)
is useful because if the base class would have been something like this
class x:
def __init__(self):
self.i=1
you would have not been able to access the attribute i from any instances of y simply because they would not have it.
Instead of calling to the init function explicitly, you should use the super() method instead.
In python 3.0+, you can jusy use:
class y(x):
def __init__(self):
super().__init__()
In python 2.7 or under, use:
class y(x):
def __init__(self):
super(self.__class__, self).__init__()
super() lets you avoid referring to the base class explicitly.
Because the child class inherits from the parent class, of course, that means everything: methods, attributes and the constructor.
So instead of rewrite all the __init__ code, you just use what is already written in the parent class.
Hope it makes sense to you.

Class variable access in all class method

I want to have a class variable, so that the value can be access in all instances, but I also want to access the variable in methods inside the class. Is that possible? I have tried this, but it didn't work at all.
class myClass:
myvariable = 1
def add():
myvariable+= 1
def print1():
print myvariable
I want to make two instances, one only do add method, the other only do print1 method
Yes, just access the variable on the class object:
class myClass(object):
myvariable = 1
def add(self):
myClass.myvariable += 1
def print1(self):
print myClass.myvariable
or if you want to set it per sub-class, use type(self):
class myClass(object):
myvariable = 1
def add(self):
type(self).myvariable += 1
def print1(self):
print type(self).myvariable
The difference is that the latter will create a separate attribute on any subclass when set, masking the base class attribute. This is just like setting an attribute on an instance would mask the class attribute.
Although you can get the class attribute via self as well (print self.myvariable), explicit is better than implicit here, and avoids accidentally being masked by an instance attribute of the same name. Setting class attributes always has to be done on the class; setting it on self would create or update an instance attribute instead (not shared).
Do inherit your classes from object though; using new-style classes has many advantages, not in the least that type(self) will then actually return the class. In old-style classes (not inheriting from object) you'd have to use self.__class__ instead.
Using object as a base also gives you a third option, class methods with the #classmethod decorator; use these when you only need to access the class object, not the instance. These methods are bound to the current (sub)class, so their effect on class attributes is the same as using type(self):
class myClass(object):
myvariable = 1
#classmethod
def add(cls):
cls.myvariable += 1
#classmethod
def print1(cls):
print cls.myvariable

Categories