Python static inheritance in class variable - python

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).

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?

Calling subsclass #classmethod from parent class

I'm trying to do the following:
class A:
#classmethod
def test_function(cls, message):
cls.__get_the_function()
class B(A):
#classmethod
def __get_the_function(cls):
return print("BBBB")
class C(A):
#classmethod
def __get_the_function(cls):
return print("CCCC")
however when I call:
B.test_function("Test")
I get the following:
AttributeError: type object 'B' has no attribute '_A__get_the_function'
I want class A to __get_the_function from the subclass (either class B or C depends on which one I use), but it looks like it is trying to look for it in itself.
NOTE: I'm using Python 3.8.2
__-prefixed names are handled specially during class creation. The name is replaced when the function is defined by a mangled name, as if you had defined the function as
#classmethod
def test_function(cls, message):
cls._A__get_the_function()
in the first place.
This is done to explicitly provide a way to hide a name from a subclass. Since you want to override the name, __get_the_function isn't an appropriate name; use an ordinary _-prefixed name if you want to mark it as private:
class A:
#classmethod
def test_function(cls, message):
cls._get_the_function()
# Define *something*, since test_function assumes it
# will exist. It doesn't have to *do* anything, though,
# until you override it.
#classmethod
def _get_the_function(cls):
pass

Get class name at class level

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().

How to find a abstract class instance and call an instance method based on the instance' attributes?

I want to call an instance method but the instance itself is unknown to me. The instance can be identified by it's attributes which I know, e.g. a unique name.
Here're my class definitions and instantiation:
from abc import ABCMeta
class MyAbstractClass():
__metaclass__ = ABCMeta
def do_something(self):
print(self.name)
class MyFirstClass(MyAbstractClass):
def __init__(self):
self.name = 'first'
class MySecondClass(MyAbstractClass):
def __init__(self):
self.name = 'second'
my_first_class_instance = MyFirstClass()
my_second_class_instance = MySecondClass()
What I want to achive is a look-up by name:
def myPrint('first'):
# should call my_first_class_instance.do_something()
def myPrint('second'):
# should call my_second_class_instance.do_something()
I looked into the built-in class methods but didn't find a way to manage the parametrization of the calls.
What's a good way of doing this?

python nested classes with adjacent inheritence?

class A(object):
class B(object): pass
class C(A.B): pass
results in
NameError: name 'A' is not defined
How do I inherit from B in C, if they are adjacent , both nested in A (inner classes)?
You cannot use A until the class body has finished executing.
You can refer to 'local' names; the class body is executed as a function, and the local namespace of that function is used to supply the class attributes; within the class body, B is a local name:
class A(object):
class B(object): pass
class C(B): pass

Categories