Python中特定类名的列表

时间:2009-11-20 14:17:20

标签: python

有没有办法标记类声明,以便以后可以获得标记的列表?

或者一种让所有类以某个字符串开头的方法?

或者是特定类的子类的所有类?

3 个答案:

答案 0 :(得分:3)

注意:以下我假设是Python 3.x.对于Python 2.x,请使用new style classes,即写class T(object): pass而不是class T: pass

  1. 首先,定义一些类:

    >>> class T: pass
    ... 
    >>> class S: pass
    ... 
    >>> class U(T): pass
    ...
    
  2. 要获取当前范围中定义的类列表,请迭代globals(或locals)并测试它们是否是type的实例(因此class!)使用isinstance

    >>> [n for n, o in globals().items() if isinstance(o, type)]
    ['S', 'U', 'T']
    
  3. 使用issubclass将搜索限制为给定类的子类(在本例中为T):

    >>> [n for n, o in globals().items() if isinstance(o, type) and issubclass(o, (T,))]
    ['U', 'T']
    
  4. 您可能想省略T本身:

    >>> [n for n, o in globals().items() if o != T and isinstance(o, type) and issubclass(o, (T,))]
    ['U']
    
  5. 要获取所有以某个字符串开头的类,请在类名称上调用startswith

    >>> [n for n, o in globals().items() if n.startswith('T') and isinstance(o, type)]
    ['T']
    
  6. 要在创建时标记某些类,请使用class decorator 添加属性,例如__flagged__

    >>> def flag(cls):
    ...     cls.__flag__ = 'flagged'
    ...     return cls
    ... 
    >>> @flag
    ... class X: pass
    ... 
    >>> @flag
    ... class Y: pass
    ... 
    >>> class Z: pass
    ... 
    
  7. 现在您只能选择那些归入__flag__属性的人:

    >>> [n for n, o in globals().items() if isinstance(o, type) and hasattr(o, '__flag__')]
    ['X', 'Y']
    

  8. :正如bobince注释,类装饰器是new in Python 2.6

答案 1 :(得分:1)

要从内部获取类的子类列表,请使用父类中的__subclasses__方法。

>>>class Parent(object):
...    pass
...
>>>class Child(Parent):
...    pass
...
>>>Parent.__subclasses__()
>>>[<class '__main__.Child'>]

不幸的是,这种方法的文档很少。

答案 2 :(得分: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'>]