Why does base class order matter when overriding #abstractmethods in base classes?
Is it possible to override abstract methods in base classes without depending on base class order?
from abc import ABC, abstractmethod
class A(ABC):
#abstractmethod
def f(self):
raise NotImplementedError
class B:
def f(self):
pass
# class C(A,B): pass # fails
class C(B,A): pass # works
While C(B,A) works, C(A,B) results in
TypeError: Can't instantiate abstract class C with abstract methods f
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?
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).
I'm working on a kind of lib, and I'm getting an error.
Here is my code. Of course #abc.abstractmethod have to be uncommented
Here are my tests
Sorry couldn't just copy and paste it
I went on the basis that the code below works.
test.py:
import abc
import six
#six.add_metaclass(abc.ABCMeta)
class Base(object):
#abc.abstractmethod
def whatever(self,):
raise NotImplementedError
class SubClass(Base):
def __init__(self,):
super(Base, self).__init__()
self.whatever()
def whatever(self,):
print("whatever")
In the python shell:
>>> from test import *
>>> s = SubClass()
whatever
For my roster module, why am I getting this error:
Can't instantiate abstract class Player with abstract methods _Base__json_builder, _Base__xml_builder
Your issue comes because you have defined the abstract methods in your base abstract class with __ (double underscore) prepended. This causes python to do name mangling at the time of definition of the classes.
The names of the function change from __json_builder to _Base__json_builder or __xml_builder to _Base__xml_builder . And this is the name you have to implement/overwrite in your subclass.
To show this behavior in your example -
>>> import abc
>>> import six
>>> #six.add_metaclass(abc.ABCMeta)
... class Base(object):
... #abc.abstractmethod
... def __whatever(self):
... raise NotImplementedError
...
>>> class SubClass(Base):
... def __init__(self):
... super(Base, self).__init__()
... self.__whatever()
... def __whatever(self):
... print("whatever")
...
>>> a = SubClass()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class SubClass with abstract methods _Base__whatever
When I change the implementation to the following, it works
>>> class SubClass(Base):
... def __init__(self):
... super(Base, self).__init__()
... self._Base__whatever()
... def _Base__whatever(self):
... print("whatever")
...
>>> a = SubClass()
whatever
But this is very tedious , you may want to think about if you really want to define your functions with __ (double underscore) . You can read more about name mangling here .
I got the same error below:
TypeError: Can't instantiate abstract class Animal with abstract methods sound
When I tried to instantiate Animal abstract class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
#abstractmethod
def sound(self):
print("Wow!!")
obj = Animal() # Here
obj.sound()
And also, I got the same error below:
TypeError: Can't instantiate abstract class Cat with abstract methods sound
When I didn't override sound() abstract method in Cat class, then I instantiated Cat class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
#abstractmethod
def sound(self):
print("Wow!!")
class Cat(Animal):
pass # I didn't override "sound()" abstract method
obj = Cat() # Here
obj.sound()
So, I overrided sound() abstract method in Cat class, then I instantiated Cat class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
#abstractmethod
def sound(self):
print("Wow!!")
# I overrided "sound()" abstract method
class Cat(Animal):
def sound(self):
print("Meow!!")
obj = Cat() # Here
obj.sound()
Then, I could solve the error:
Meow!!
Easiest way to make it behave like it did in Python 2 is to use
exec('print("your code")', globals())
This will allow your code to access imports, classes and functions defined in the code will work correctly, etc.
This should only be done w/ code you trust.
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