动态检索模块/脚本中声明的python类的元信息

动态检索模块/脚本中声明的python类的元信息,python,class,oop,metaprogramming,Python,Class,Oop,Metaprogramming,我有一组类,我希望能够从dict动态初始化它们 class A(object): var = 1 class B(object): val = 2 class C(object): var = 1 val = 3 BASE = {'a': A, 'b': B, 'c': C} 我可能会在一些动态函数中使用这些函数,例如 def create_and_obtain(kind, **kwargs): base = BASE[kind]() fo

我有一组类,我希望能够从dict动态初始化它们

class A(object):
    var = 1

class B(object):
    val = 2

class C(object):
    var = 1
    val = 3

BASE = {'a': A, 'b': B, 'c': C}
我可能会在一些动态函数中使用这些函数,例如

def create_and_obtain(kind, **kwargs):
    base = BASE[kind]()
    for kwarg in kwargs.keys():
        print(getattr(base, kwarg))
>>> create_and_obtain('c', var=None, val=None)
1
3
如果我有很多类,这些类会不时添加、修改和删除,我必须确保我的
BASE
dict保持最新。是否有一种方法可以根据脚本中声明的类动态构造
BASE
?类本身是否可以添加任何meta_属性来扩展
BASE
的定义,使其超出这个简单的示例

例如,我可以添加一些元标记,如:

class A(object):
    ...
    _meta_dict_key_ = 'apples'
class B(object):
    ...
    _meta_dict_key_ = 'bananas'
class C(object):
    ...
    _meta_dict_key_ = 'coconuts'
因此,
BASE
动态构造为:

BASE = {'apples': A, 'bananas': B, 'coconuts':C} 

您可以迭代文件末尾的
locals()
函数的输出,并检查_meta\u dict\u键。如果对象中有这样的键,则可以使用它来构造基本dict。
在python中,文件顶级上声明的所有代码在第一次导入时只执行一次,因此可以安全地将这些代码放在那里。

您可以迭代文件末尾的
locals()
函数的输出,并选中_meta\u dict\u键。如果对象中有这样的键,则可以使用它来构造基本dict。
在python中,文件top-level上声明的所有代码在第一次导入时只执行一次,因此可以安全地将这些代码放在那里。

python具有类装饰器,因此一种干净的方法可能是:

BASE = {}

def register(klass):  # Uses an attribute of the class
    global BASE
    BASE[klass.name] = klass
    return klass

def label(name):  # Provide an explicit name
    def deco(klass):
        global BASE
        BASE[name] = klass
        return klass
    return deco

@register
class A(object):
    var = 1
    name = 'bananas'

@label('apples')
class B(object):
    val = 2

@register
class C(object):
    var = 1
    val = 3
    name = 'cakes'

Python有类装饰器,因此一种干净的方法可能是:

BASE = {}

def register(klass):  # Uses an attribute of the class
    global BASE
    BASE[klass.name] = klass
    return klass

def label(name):  # Provide an explicit name
    def deco(klass):
        global BASE
        BASE[name] = klass
        return klass
    return deco

@register
class A(object):
    var = 1
    name = 'bananas'

@label('apples')
class B(object):
    val = 2

@register
class C(object):
    var = 1
    val = 3
    name = 'cakes'

您还可以定义decorator,使其将name/key作为参数,而不是将其定义为类上的属性。您还可以定义decorator,使其将name/key作为参数,而不是将其定义为类上的属性。