简体   繁体   English

python3:将字符串转换为类型

[英]python3: convert string to type

I have a set of classes A , B , C in a "front end" package p1 . 我在“前端”包p1有一组类ABC They all inherit from p1.X . 它们都继承自p1.X

I have another set of classes A , B , C in a "back end" package p2 . 我在“后端”包p2有另一组类ABC They all inherit from p2.Y . 它们都继承自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. p1.X ,我设置了一个后端,以便p1.A使用p2.A作为后端, p1.B使用p2.B等。此映射是基于继承方法中的类名完成的。

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. 现在,我想拥有例如backend = "p2.A" (字符串),但是当我尝试对此求值时,python不知道p2 ,即使它是较早导入的。

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: PS:我目前在“父级” p1.X类中有类似的内容,这很糟糕,但是很好地阐明了我想要的内容:

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. 小小的hacky解决方案,但是应该可以使用,并且没有经过硬编码。

p2.py: 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. 每当获取backend_class属性时,它将调用它的__get__方法并返回该调用的结果。 The BackendClassFetcher is known as a non-data descriptor. BackendClassFetcher被称为非数据描述符。

package1/m1.py 包1 / 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 包1 / m2.py

class Parent: pass
class A(Parent): pass
class B(Parent): pass
class C(Parent): pass

You can use import_module . 您可以使用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. 关于cython的评论:即使“纯cython” cdef类/ cpdef方法,也必须导入后端,而不是cimport。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM