在python中获取类的类路径或名称空间,即使它是嵌套的 [英] getting the class path or name space of a class in python even if it is nested

查看:179
本文介绍了在python中获取类的类路径或名称空间,即使它是嵌套的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在用Python编写一个序列化模块,该模块可以序列化用户定义的类.为此,我需要获取对象的完整名称空间并将其写入文件.然后,我可以使用该字符串来重新创建对象.

I'm currently writing a serialization module in Python that can serialize user defined classes. in order to do this I need to get the full name space of the object and write it to a file. I can then use that string to recreate the object.

例如,假设我们在名为A.py

for example assume that we have the following class structure in a file named A.py

class B:
    class C:
        pass

现在假设my_klass_string是字符串"A::B::C"

klasses = my_klass_string.split("::")
if globals().has_key(klasses[0]):   
    klass = globals()[klasses[0]]
else:
    raise TypeError, "No class defined: %s} " % klasses[0]
if len(klasses) > 1:
    for klass_string in klasses:
        if klass.__dict__.has_key(klass_string):
            klass = klass.__dict__[klass_string]
        else:
            raise TypeError, "No class defined: %s} " % klass_string            
klass_obj = klass.__new__(klass)

我可以创建类C的实例,即使它位于模块A中的类B下. 上面的代码等效于调用eval(klass_obj = A.B.C.__new__(A.B.C))

I can create an instance of the class C even though it lies under class B in the module A. the above code is equivalent to calling eval(klass_obj = A.B.C.__new__(A.B.C))

注意: 我在这里使用__new__()是因为我要重构一个序列化的对象,并且由于不知道类的__init__方法采用什么参数,所以不想初始化该对象.我想在不调用 init 的情况下创建对象,然后再为其分配属性.

note: I'm using __new__() here because I'm reconstituting a serialized object and I don't want to init the object as I don't know what parameters the class's __init__ methods takes. I want to create the object with out calling init and then assign attributes to it later.

以任何方式可以从字符串创建类A.B.C的对象.关于如何走另一条路?即使该类是嵌套的,如何从该类的实例获取描述该类的完整路径的字符串?

any way I can create an object of class A.B.C from a string. bout how do I go the other way? how to I get a string that describes the full path to the class from an instance of that class even if the class is nested?

推荐答案

在给定实例的情况下,您无法获得该类的完整路径" 类",原因是Python中没有这样的东西. 实例,以您的示例为基础:

You cannot get the "full path to the class given an instance of the class", for the reason that there is no such thing in Python. For instance, building on your example:

>>> class B(object):
...     class C(object):
...             pass
... 
>>> D = B.C
>>> x = D()
>>> isinstance(x, B.C)
True

x的类路径"应该是什么? DB.C?两者都是 同样有效,因此Python不会给您任何手段来告诉一个人 从另一个.

What should the "class path" of x be? D or B.C? Both are equally valid, and thus Python does not give you any means of telling one from the other.

实际上,甚至Python的pickle模块也很难对对象x进行酸洗:

Indeed, even Python's pickle module has troubles pickling the object x:

>>> import pickle
>>> t = open('/tmp/x.pickle', 'w+b')
>>> pickle.dump(x, t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/pickle.py", line 1362, in dump
    Pickler(file, protocol).dump(obj)
  ...
  File "/usr/lib/python2.6/pickle.py", line 748, in save_global
   (obj, module, name))
  pickle.PicklingError: Can't pickle <class '__main__.C'>: it's not found as __main__.C

因此,总的来说,除了添加属性外,我没有其他选择 到您所有的类(例如,_class_path),并且您的序列化代码将对其进行查找 将类名称记录为序列化格式:

So, in general, I see no other option than adding an attribute to all your classes (say, _class_path), and your serialization code would look it up for recording the class name into the serialized format:

class A(object):
  _class_path = 'mymodule.A'
  class B(object):
    _class_path = 'mymodule.A.B'
    ...

您甚至可以使用一些元类魔术来自动执行此操作(但也请阅读同一篇SO帖子中的其他评论 a>对于如果您执行上述D=B.C可能需要注意的事项).

You can even do this automatically with some metaclass magic (but also read the other comments in the same SO post for caveats that may apply if you do the D=B.C above).

也就是说,如果您可以将序列化代码限制为(1)个实例 (2)这些类是在 模块的顶层,那么您只需复制pickle的内容即可 (来自Python的pickle.py中的730--768行处的函数save_global 2.6).

That said, if you can limit your serialization code to (1) instances of new-style classes, and (2) these classes are defined at the top-level of a module, then you can just copy what pickle does (function save_global at lines 730--768 in pickle.py from Python 2.6).

这个想法是,每个新式类都定义属性__name____module__,它们是扩展为类名的字符串(如 在源代码中找到)和模块名称(在 sys.modules);通过保存这些,您以后可以导入模块并 获取该类的实例:

The idea is that every new-style class defines attributes __name__ and __module__, which are strings that expand to the class name (as found in the sources) and the module name (as found in sys.modules); by saving these you can later import the module and get an instance of the class:

__import__(module_name)
class_obj = getattr(sys.modules[module_name], class_name)

这篇关于在python中获取类的类路径或名称空间,即使它是嵌套的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆