Getting the name of a class which has a meta class - python

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)

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.

Where is the __bases__ attribute defined?

​‫I define a python class in python interpreter
class A:
pass
I get base class of A using A.__bases__, it shows
(object,)
but when I enter dir(A), the output don't contain __bases__ attribute, then I try dir(object), __bases__ is not found either, where does the __bases__ come from?
The __bases__ attribute in a class is implemented by a descriptor in the metaclass, type. You have to be a little careful though, since type, as one of the building blocks of the Python object model, is an instance of itself, and so type.__bases__ doesn't do what you would want for introspection.
Try this:
descriptor = type.__dict__['__bases__']
print(descriptor, type(descriptor))
You can reproduce the same kind of thing with your own descriptors:
class MyMeta(type):
#property # a property is a descriptor
def foo(cls):
return "foo"
class MyClass(metaclass=MyMeta):
pass
Now if you access MyClass.foo you'll get the string foo. But you won't see foo in the variables defined in MyClass (if you check with vars or dir). Nor can you access it through an instance of MyClass (my_obj = MyClass(); my_obj.foo raises an AttributeError).
it is a special attribute akin to __name__ or __dict__. While the result of function dir actually depends on the implementation of __dir__ function.
You might want to look it on the doc here https://docs.python.org/3/reference/datamodel.html

Conceptual questions about class, sub class and attributes in programming using python

In python, when I'm inheriting a class. what exactly am I inheriting? am I inheriting the class attributes? if yes, then does that mean I'm inheriting their default values too? and finally, do I necessarily have to set a default value or even mention the attributes in sub-class when I declare that I'm inheriting a class. Basically, what is the point of redeclaring the attributes in a subclass if there is any??
Taken from the official documentation:
Execution of a derived class definition proceeds the same as for a base class. When the class object is constructed, the base class is remembered. This is used for resolving attribute references: if a requested attribute is not found in the class, the search proceeds to look in the base class. This rule is applied recursively if the base class itself is derived from some other class.
The following example should demonstrate that:
class A:
foo = 0
class B(A):
pass
# 'foo' isn't found in 'B' and the search proceeds in 'A'.
print(B.foo) # output: 0
If an attribute is defined in a subclass and in it's base, then a second attribute is created which is only defined in the subclass and takes precedence when being accessed. Example:
class A:
foo = 1
class B(A):
foo = 2
# 'A.foo' is a different object than 'B.foo'.
print(A.foo) # output: 1
print(B.foo) # output: 2

Python style with attributes in class definition

I have a class with some attributes I want to use the methods. What is the most pythonic way to use it?. Is there documentation I can read about these styles issues?. I use pylint and pep8 to fix this kind of issues, but these program don't show any errors in this example with the attribute
class A(object):
BLOCK_SIZE = 8192
def func1(self):
print self.BLOCK_SIZE
def func2(self):
print A.BLOCK_SIZE
If I understand correctly this two case are the same, but I don't
know if is better to refer the class name or use the self reference.
Thanks
You should prefer self.
There are two types of fields - Class variables and Object variables.
Class variables are shared in the sense that they are accessed by all objects (instances) of that class. There is only copy of the class variable and when any one object makes a change to a class variable, the change is reflected in all the other instances as well.
Object variables are owned by each individual object/instance of the class. In this case, each object has its own copy of the field i.e. they are not shared and are not related in any way to the field by the same name in a different instance of the same class.
By using A.BLOCK_SIZE - you get class variable while by using self.BLOCK_SIZE you get an attribute of the specific object.
Check this to get a detailed example and explanations.
https://www.ibiblio.org/g2swap/byteofpython/read/class-and-object-vars.html
A class attribute can more or less be used as the default value for an instance attribute. The language allow a class attribute to be read either from the class itself or from any instance of the class, provided the instance has no attribute of same name.
But things go differently for write access: A.BLOCK_SIZE=16384 will change the global class attribute, while self.BLOCK_SIZE=16384 will create (or update) an instance attribute of same name.
Here is a little example with your class:
>>> a = A()
>>> a.func1() # access the class attribute
8192
>>> a.func2() # access the class attribute too
8192
>>> a.BLOCK_SIZE=4096 # create an instance attribute of same name
>>> a.func1() # access the INSTANCE attribute
4096
>>> a.func2() # still access the class attribute
8192
That's the reason why you should under common circonstances use the instance semantics (self.BLOCK_SIZE) because it does not rely on the class name and allows per instance override.
The class semantics A.BLOCK_SIZE should only be used if you want to change the class attribute, or need to use the class attribute even if an instance attribute exists.

error when using method defined parent class

I have the following classes:
class A:
def name(self):
return self.__label
class B(A):
def __init__(self, name)
self.__label = name
ex1 = B('Tom')
print ex1.name()
What I get is:
AttributeError: B instance has no attribute '_A__label'
What's wrong and how to correct it?
When you prefix an attribute with a double underscore, Python uses 'name mangling' to access the attribute. This means it will store the attribute on the class in the format: _<class name>__<attr name>. In your example self.__label will be stored as self._B__label because you set it in the B class method. But when you try to use the attribute in the A class it converts self.__label into self._A__label and finds that it isn't set.
The use case for double underscores is when you want to ensure that your variable is always on your class even if a subclass derives your class. Because what could happen is that the subclass redefines your variable to something else, using double underscored variables makes this that much harder.

Categories