按照它们定义的顺序在类中查找嵌套的子类

时间:2014-04-24 14:02:19

标签: python class oop python-2.5

想象一下这样的案例:

class A:
    pass

class B:
    x = 5
    class D(A):
        pass
    class C(A):
        pass

我想要的是找到类B中属于A的子类的所有类:

>>> for cls in dir(B):
    if issubclass(cls, A):
        print(cls)
<class '__main__.C'>
<class '__main__.D'>

它按预期工作,但问题是:我需要按照它们在class B定义中的定义来获取它们,所以不要在D之前打印C,而是需要在C之前得到D. dir()显然不起作用,因为它返回按字母顺序排序的列表。 如果有的话,我的其他选择是什么?

修改 我想要这个的原因是为了帮助#34;玩家&#34;尽可能轻松地制作自己的英雄/冠军(视频游戏)。所以不必写:

class MyHero(Hero):
     def __init__(self, name='My Hero', description='My description', ...):
          super().__init__(name, description, ...)
          self.spells = [MySpell1(), MySpell2(), MySpell3()]

class MySpell1(Spell):
     def __init__(...):
          ...

他们可以写:

class MyHero(Hero):
    name = 'My Hero'
    description = 'My description'
    ...

    class MySpell1(Spell):
        name = ...

    class MySpell2(Spell):
        ...

显然,第二个看起来比第一个好得多,对于一个对Python知之甚少的人来说更是如此。

2 个答案:

答案 0 :(得分:3)

元类文档包含一个很好的example如何使类记住其成员的定义顺序:

class OrderedClass(type):

     @classmethod
     def __prepare__(metacls, name, bases, **kwds):
        return collections.OrderedDict()

     def __new__(cls, name, bases, namespace, **kwds):
        result = type.__new__(cls, name, bases, dict(namespace))
        result.members = tuple(namespace)
        return result

class A(metaclass=OrderedClass):
    def one(self): pass
    def two(self): pass
    def three(self): pass
    def four(self): pass 


>>> A.members
('__module__', 'one', 'two', 'three', 'four')

你可以像这样适应你的情况:

class A:
    pass

class B(metaclass=OrderedClass):
    x = 5
    class D(A):
        pass
    class C(A):
        pass

print(filter(lambda x: isinstance(getattr(B, x), type), b.members)))

给出:

['D', 'C']

请注意,这会为您提供类的名称;如果你想要自己的类,你可以这样做:

print(list(filter(lambda x: isinstance(x, type), (getattr(B, x) for x in B.members))))

答案 1 :(得分:1)

可能会有所帮助:

import inspect

class Spell(object):
    name = "Abstract spell"

class MyHero(object):
    name = "BATMAN"
    description = "the bat man"

    class MySpell1(Spell):
        name = "Fly"

    class MySpell2(Spell):
        name = "Sleep"


for k, v in MyHero.__dict__.iteritems():
    if inspect.isclass(v) and issubclass(v, Spell):
        print "%s cast the spell %s" % (MyHero.name, v.name)

<强>更新

按类属性迭代的另一种方法是:

for attr_name in dir(MyHero):
    attr = getattr(MyHero, attr_name)
    if inspect.isclass(attr) and issubclass(attr, Spell):
        print "%s cast the spell %s" % (MyHero.name, attr.name)

P.S。 Python类也是对象