I have a set of classes A
, B
, C
in a "front end" package p1
. They all inherit from p1.X
.
I have another set of classes A
, B
, C
in a "back end" package p2
. They all inherit from p2.Y
.
In p1.X
, I set one backend, so that p1.A
uses p2.A
as backend, p1.B
uses p2.B
, etc. This mapping is done based on the class name in an inherited method.
Now, I suceed to have, for example, backend = "p2.A"
(string), but when I try to eval this, python doesn't knows about p2
, even if this is imported earlier.
What did I do wrong? Should I import inside the eval? Should like spaghetti code... Do you have a better idea?
Thanks.
PS: I currently have something like this in the "parent" p1.X
class, which is awful, but good to clarify what I want:
def getBackendClass(self):
myClass = ... # (class without package name)
if myClass == "A":
return p2.A
elif myClass == "B":
return p2.B
...
Little hacky solution, but should work, and is not hardcoded.
p2.py:
class Y(object):
@classmethod
def fromString(cls, s):
cls_name = s.split(".")[1]
for c in cls.__subclasses__():
if c.__name__() == cls_name:
return c()
raise ValueError("%s not found in subclasses" % s)
Perhaps you mean something like this? Whenever the backend_class
attribute is fetched it will call it's __get__
method and return the result of that call. The BackendClassFetcher
is known as a non-data descriptor.
package1/m1.py
from . import p2
class BackendClassFetcher:
def __get__(self, obj, objtype):
return getattr(p2, objtype.__name__)
class Parent:
backend_class = BackendClassFetcher()
class A(Parent): pass
class B(Parent): pass
class C(Parent): pass
for cls in [A,B,C]:
obj = cls()
print(cls, cls.backend_class, obj.backend_class)
package1/m2.py
class Parent: pass
class A(Parent): pass
class B(Parent): pass
class C(Parent): pass
You can use import_module
. Documentation
sample:
from importlib import import_module
path = "p2.A"
cls_name = path.split('.')[-1]
module_path = ".".join(path.split('.')[:-1])
module = import_module(module_path)
cls = getattr(module, cls_name)
Good luck.
Thanks a lot. I've made a mix of all your answers, leading the following code in the front end:
import backend
class Parent:
@property
def backend_class(self):
return getattr(backend, self.__class__.__name__)
class A(Parent):
pass
if __name__ == "__main__":
instance = A()
backendInstance = instance.backend_class()
Comment about cython: the backend must be imported, not cimported, even if "pure cython" cdef
classes/ cpdef
methods.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.