python nested classes with adjacent inheritence? - python

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

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

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

Python: Inherit from a class from containing class

When I am running the following code:
class A(object):
class B(object):
pass
class C(object):
class D(A.B):
pass
I get an error on creating class D:
NameError: name 'A' is not defined
Is it possible to create D which inherits from B without extraction of any class outside A?

Variable not found in the outer class scope

I have this code:
class Attributes(object):
class __metaclass__(type):
def __init__(self, cls_name, cls_bases, cls_dict):
# super(Attributes.__metaclass__, self) # NameError: global name 'Attributes' is not defined
super(__metaclass__, self).__init__(
cls_name, cls_bases, cls_dict)
gives
NameError: global name '__metaclass__' is not defined
Why __metaclass__ variable is not found in the outer scope?
try this instead
super(Attributes.__metaclass__, self).__init__(cls_name, cls_bases, cls_dict)
While creating a class, only its name is visible. Its contents does not exist yet until the class is finished being created. The parts inside the class, therefore, cannot access any fields of the class during creation. So you will need to use fully qualified names to denote that you want to access fields of the class
You are currently creating a class SimpleModel and while doing so you are creating a class Attributes and while doing so a class __metaclass__. Since while you do this, the class SimpleModel isn't existing yet, the method __init__ is not yet part of anything existing. It first gets created and then, later, will be made part of the class __metaclass__. Hence it cannot know the identifier __metaclass__. And since __metaclass__ also never becomes a global, when called, this identifier cannot be known.
That's the reason why you have no __metaclass__ in your scope at this point, but when later __init__ gets called, only a SimpleModel is available via the global scope, so you can base your name on it: SimpleModel.Attributes.__metaclass__.
Looks like the answer is this:
Outer scope for a method is not class body, but outer function in which the class is contained or the module.
That's why in the case of
class Test():
attr_1 = 'smth'
def a_method(self):
attr_1 # not visible on this line
attr_1 is not visible inside method Test.a_method
And the solution is to define metaclass at global level:
class AttributesMeta(type):
def __init__(self, cls_name, cls_bases, cls_dict):
super(__metaclass__, self).__init__(
cls_name, cls_bases, cls_dict)
class Attributes(object):
__metaclass__ = AttributesMeta

Categories