有没有办法标记类声明,以便以后可以获得标记的列表?
或者一种让所有类以某个字符串开头的方法?
或者是特定类的子类的所有类?
答案 0 :(得分:3)
注意:以下我假设是Python 3.x.对于Python 2.x,请使用new style classes,即写class T(object): pass
而不是class T: pass
。
首先,定义一些类:
>>> class T: pass
...
>>> class S: pass
...
>>> class U(T): pass
...
要获取当前范围中定义的类列表,请迭代globals
(或locals
)并测试它们是否是type
的实例(因此class!)使用isinstance
:
>>> [n for n, o in globals().items() if isinstance(o, type)]
['S', 'U', 'T']
使用issubclass
将搜索限制为给定类的子类(在本例中为T
):
>>> [n for n, o in globals().items() if isinstance(o, type) and issubclass(o, (T,))]
['U', 'T']
您可能想省略T
本身:
>>> [n for n, o in globals().items() if o != T and isinstance(o, type) and issubclass(o, (T,))]
['U']
要获取所有以某个字符串开头的类,请在类名称上调用startswith
:
>>> [n for n, o in globals().items() if n.startswith('T') and isinstance(o, type)]
['T']
要在创建时标记某些类,请使用class decorator †添加属性,例如__flagged__
:
>>> def flag(cls):
... cls.__flag__ = 'flagged'
... return cls
...
>>> @flag
... class X: pass
...
>>> @flag
... class Y: pass
...
>>> class Z: pass
...
现在您只能选择那些归入__flag__
属性的人:
>>> [n for n, o in globals().items() if isinstance(o, type) and hasattr(o, '__flag__')]
['X', 'Y']
†:正如bobince注释,类装饰器是new in Python 2.6。
答案 1 :(得分:1)
您还可以使用元类收集定义的类:
class AllSeeingMetaClass(type):
# This will be a list of all the classes that use us as a metaclass.
the_classes = []
def __new__(meta, classname, bases, classDict):
# Invoked as new classes are defined.
print "Defining %r" % classname
new_class = type.__new__(meta, classname, bases, classDict)
meta.the_classes.append(new_class)
return new_class
class MyBase(object):
# A base class that pulls in our metaclass.
__metaclass__ = AllSeeingMetaClass
class Cat(MyBase):
def __init__(self):
pass
class Dog(MyBase):
def __init__(self):
pass
print AllSeeingMetaClass.the_classes
打印:
Defining 'MyBase'
Defining 'Cat'
Defining 'Dog'
[<class '__main__.MyBase'>, <class '__main__.Cat'>, <class '__main__.Dog'>]
答案 2 :(得分:1)
要从内部获取类的子类列表,请使用父类中的__subclasses__方法。
>>>class Parent(object):
... pass
...
>>>class Child(Parent):
... pass
...
>>>Parent.__subclasses__()
>>>[<class '__main__.Child'>]
不幸的是,这种方法的文档很少。