Get class name at class level - python

Is there a way to get the name of a class at class level in Python?
Minimum working example:
class TestClass:
print("We are now in the class {} at class level".format(WHAT SHOULD I PUT HERE?)) # Should return "We are now in the class TestClass at class level"
pass

Here's how you can find out:
class TestClass:
print(locals())
This prints:
{'__module__': '__main__', '__qualname__': 'TestClass'}
So you can use __qualname__, i.e.
class TestClass:
print("We are now in the class {} at class level".format(__qualname__))

This works :
class Test :
CLASSNAME = locals()['__qualname__']
Use the CLASSNAME variable anywhere in the class or outside.

For defined classes only: Use type(self).__name__ where .__name__ is a default attribute.
Refer to #Alex Hall's answer for using the class name before __init__ takes place, using locals().

Related

Why python class definition can refer to a concrete class instance name?

For example:
class abc:
def show(self):
print(self)
print(a)
a = abc()
a.show()
Here a is an instance of the class, which can be directly referred to in the method by its name, in addition to by the first argument self.
Why is this allowed?

Python: Predefined class variable access

In Python, I am able to access the non-predefined class variables both from the class as well as instances. However, I am not able to access the predefined class variables (such as "name") from the object instances. What am I missing? Thanks.
Here is a test program that I wrote.
class Test:
'''
This is a test class to understand why we can't access predefined class variables
like __name__, __module__ etc from an instance of the class while still able
to access the non-predefined class variables from instances
'''
PI_VALUE = 3.14 #This is a non-predefined class variable
# the constructor of the class
def __init__(self, arg1):
self.value = arg1
def print_value(self):
print self.value
an_object = Test("Hello")
an_object.print_value()
print Test.PI_VALUE # print the class variable PI_VALUE from an instance of the class
print an_object.PI_VALUE # print the class variable PI_VALUE from the class
print Test.__name__ # print pre-defined class variable __name__ from the class
print an_object.__name__ #print the pre-defined class varible __name__ from an instance of the class
That's normal. Instances of a class look in that class's __dict__ for attribute resolution, as well as the __dict__s of all ancestors, but not all attributes of a class come from its __dict__.
In particular, Test's __name__ is held in a field in the C struct representing the class, rather than in the class's __dict__, and the attribute is found through a __name__ descriptor in type.__dict__. Instances of Test don't look at this for attribute lookup.
I don't have a great answer for "why". But here's how you can get to them, using __class__:
>>> class Foo(object): pass
...
>>> foo = Foo()
>>> foo.__name__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__name__'
>>> foo.__class__.__name__
'Foo'
>>>

Python static inheritance in class variable

In python, is there a way to get the class name in the "static constructor"? I would like to initialize a class variable using an inherited class method.
class A():
#classmethod
def _getInit(cls):
return 'Hello ' + cls.__name__
class B(A):
staticField = B._getInit()
NameError: name 'B' is not defined
The name B is not assigned to until the full class suite has been executed and a class object has been created. For the same reason, the __name__ attribute on the class is not set until the class object is created either.
You'd have to assign that attribute afterwards:
class A():
#classmethod
def _getInit(cls):
return 'Hello ' + cls.__name__
class B(A):
pass
B.staticField = B._getInit()
The alternative is to use a class decorator (which is passed the newly-created class object) or use a metaclass (which creates the class object in the first place and is given the name to use).

Can't access parent member variable in Python

I'm trying to access a parent member variable from an extended class. But running the following code...
class Mother(object):
def __init__(self):
self._haircolor = "Brown"
class Child(Mother):
def __init__(self):
Mother.__init__(self)
def print_haircolor(self):
print Mother._haircolor
c = Child()
c.print_haircolor()
Gets me this error:
AttributeError: type object 'Mother' has no attribute '_haircolor'
What am I doing wrong?
You're mixing up class and instance attributes.
print self._haircolor
You want the instance attribute, not the class attribute, so you should use self._haircolor.
Also, you really should use super in the __init__ in case you decide to change your inheritance to Father or something.
class Child(Mother):
def __init__(self):
super(Child, self).__init__()
def print_haircolor(self):
print self._haircolor

Python: __str__, but for a class, not an instance?

I understand the following Python code:
>>> class A(object):
... def __str__(self):
... return "An instance of the class A"
...
>>>
>>> a = A()
>>> print a
An instance of the class A
Now, I would like to change the output of
>>> print A
<class '__main__.A'>
Which function do I need to overload to be able to do that? The solution has to work even if the class is never instantiated. Is the situation different in Python 2.x and 3?
Define __str__() on the metaclass:
class A(object):
class __metaclass__(type):
def __str__(self):
return "plonk"
Now, print A will print plonk.
Edit: As noted by jsbueno in the comments, in Python 3.x you would need to do the following:
class Meta(type):
def __str__(self):
return "plonk"
class A(metaclass=Meta):
pass
Even in Python 2.x it might be a better idea to define the metaclass outside the class body -- I chose the nested form above to save some typing.
Define the __repr__ method on your meta class:
class MetaClass(type):
def __repr__(self):
return "Customized string"
class TestClass(object):
__metaclass__ = MetaClass
print TestClass # Customized string

Categories