2015-06-11 2 views
-1

У меня есть набор классов A, B, C в пакете «front end» p1. Они все наследуют от p1.X.python3: преобразовать строку в тип

У меня есть еще один набор классов A, B, C в пакете p2 «задний конец». Они все наследуют от p2.Y.

В p1.X, я поставил один бэкенд, так что p1.A использует p2.A в качестве внутреннего интерфейса, p1.B использует p2.B и т.д. Это отображение осуществляются на основе имени класса в унаследованном методе.

Теперь у меня есть, например, backend = "p2.A" (строка), но когда я пытаюсь это сделать, python не знает о p2, даже если это импортировано ранее.

Что я сделал не так? Должен ли я импортировать внутри eval? Мне нужен код спагетти ... У вас есть идея?

Спасибо.

PS: Я в настоящее время есть что-то подобное в «родитель» p1.X класса, который ужасно, но хорошо, чтобы выяснить, что я хочу:

def getBackendClass(self): 
    myClass = ... # (class without package name) 
    if myClass == "A": 
      return p2.A 
    elif myClass == "B": 
      return p2.B 
    ... 
+0

Почему бы не иметь сопоставление '{classname: class}', а затем использовать 'getattr' для доступа к методу? – jonrsharpe

+0

Спасибо, Джон, но я намерен избегать жесткого кодирования этого. В вашем примере у меня должен быть '{p1.A: p2.A, p2.B: p2.B, ...}' (у меня есть A, B, ...равное более или менее 30 разных классов). Отображение является систематическим (я использовал скрипт vim для его написания ...). –

ответ

0

Большое спасибо. Я сделал микс из всех ваших ответов, приводя следующий код в передней части:

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

комментарий о Cython: бэкенд должен быть импортирован, не cimported, даже если «чистый Cython» cdef классов/cpdef методы.

1

Маленький Hacky решение, но он должен работать, и не жёстко.

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

Возможно, вы имели в виду что-то вроде этого? Всякий раз, когда вызывается атрибут backend_class, он называет его __get__ и возвращает результат этого вызова. BackendClassFetcher известен как дескриптор без данных.

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 
0

Вы можете использовать import_module. Documentation

образец:

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) 

удачи.

Смежные вопросы