Imagine a case like so:
class A:
pass
class B:
x = 5
class D(A):
pass
class C(A):
pass
What I want is to find all the classes in class B
that are subclasses of A
:
>>> for cls in dir(B):
if issubclass(cls, A):
print(cls)
<class '__main__.C'>
<class '__main__.D'>
And it works as intended, but the problem is: I need to get them in the order they are defiend in class B
definition, so instead of printing C before D, I need to get D before C. Using dir()
obviously doesn't work, since it returns alphabetically sorted list. What are my other options, if any?
EDIT: The reason I want this is to help "players" make their own heroes/champions (for a video game) as easily as possible. So instead of having to write:
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__(...):
...
They could just write:
class MyHero(Hero):
name = 'My Hero'
description = 'My description'
...
class MySpell1(Spell):
name = ...
class MySpell2(Spell):
...
Obviously the second one looks much better than the first, and even more to a person who doesn't know much of Python.
The metaclass documentation includes a nice example of how to get a class to remember what order its members were defined in:
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')
You can adapt this to your case like this:
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)))
gives:
['D', 'C']
Note that this gives you the names of the classes; if you want the classes themselves, you can do this instead:
print(list(filter(lambda x: isinstance(x, type), (getattr(B, x) for x in B.members))))
May be something like that can be helpful:
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)
UPDATE :
Another way to iterate by class attributes is:
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)
PS Python class is also object
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.