【问题标题】:python - how to get a list of inner classes?python - 如何获取内部类的列表?
【发布时间】:2017-07-08 15:51:29
【问题描述】:

我正在编写一个包含一些嵌套类的小型 Python 应用程序,如下例所示:

class SuperBar(object):
    pass

class Foo(object):
    NAME = 'this is foo'

    class Bar(SuperBar):
        MSG = 'this is how Bar handle stuff'

    class AnotherBar(SuperBar):
        MSG = 'this is how Another Bar handle stuff'

我使用嵌套类来创建某种层次结构并提供一种简洁的方式来实现解析器的功能。

在某些时候,我想创建一个内部类列表。我想要以下输出:

[<class '__main__.Bar'>, <class '__main__.AnotherBar'>]

问题是:以pythonic方式获取内部类列表的推荐方法是什么?

【问题讨论】:

  • 1.你为什么要嵌套类,你能提供更多的上下文吗? 2. 你不只想要SuperBar 的所有子类(在这种情况下参见stackoverflow.com/q/3862310/3001761)?
  • 这还不够。在实际应用中我有更多的根类,比如Foo,还有更多的内部类来完成解析树。我还需要强制在根令牌Foo 的上下文中找到找到的给定令牌(如Bar)。为了捕捉这种层次结构,我使用了这些内部类。 -- 谢谢
  • 然后edit 提供更多上下文。您可能试图完全解决错误的问题。

标签: python python-2.7 python-3.x inner-classes metaclass


【解决方案1】:

我设法通过以下方法获得了内部类对象的列表:

import inspect

def inner_classes_list(cls):
    return [cls_attribute for cls_attribute in cls.__dict__.values()
            if inspect.isclass(cls_attribute)
            and issubclass(cls_attribute, SuperBar)]

它有效,但我不确定直接使用__dict__ 是否是一件好事。我使用它是因为它包含我需要的实际 class 实例,并且似乎可以跨 Python 2 和 3 移植。

【讨论】:

  • 是的 - 你可以使用 dict - 这是更常见的地方,并且使用嵌套类更有用。 – 但是有一个问题,通过查看__dict__,您看不到超类的任何属性。检查我的答案。
【解决方案2】:

首先:我看不出嵌套类对你有什么用处。一旦你有一个实例fFoo,你是否意识到f.Barf.AnotherBar 将是所有实例的同一个对象?也就是说 - 您不能在 f.Bar 上记录来自 f 的任何特定属性,例如 f.Bar.speed - 否则它将与来自另一个实例 g.Bar.speed 的属性发生冲突。

要克服这一点,实际上,唯一有意义的事情是,您需要将BarAnotherBar 的实例附加到实例f。这些实例通常不能在类主体上声明 - 您必须在 Foo 的 __init__ 方法上创建它们。

Bar 和 AntherBar 唯一能做的就是:(1)有很多类和静态方法,然后它们只作为命名空间工作。

或者,如果 SuperBar 的元类或它们自己实现了描述符协议 - https://docs.python.org/3/reference/datamodel.html#implementing-descriptors - 但是它们,如果 superbar 本身实现描述符协议(通过使用 __get____set__ 方法),并附加到 Foo 的主体上,您将拥有这些类的实例,而不是类本身。

也就是说,您提供了使用__dict__ 获取内部类的解决方案:如果Foo 本身继承自其他也具有嵌套类的类,则该解决方案将不起作用。永远不会搜索 Foo 的超类。您可以有一种方法来查看 Foo 的 __mro__ 上的所有类,或者简单地使用 dirissubclass

class Foo:
     @classmethod
     def inner_classes_list(cls):
          results = []
          for attrname in dir(cls):
              obj = getattr(cls, attrname)
              if isinstance(obj, type) and issubclass(obj, SuperBar):
                   results.append(obj)
          return results

(如果您希望它适用于像 Foo 这样不共享公共基础的所有类,那么如果将它声明为类方法,则相同的代码当然可以工作 - 而且,SuperBar 可以是此函数的参数,如果您有多个嵌套类层次结构。)

现在你有了这个,我们敦促你问其他问题,说明你想实际做什么 - 并阅读“描述符” - 甚至“属性”。真的:嵌套子类几乎没有什么用处。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 2012-01-12
    • 2022-01-16
    • 2021-01-16
    • 1970-01-01
    相关资源
    最近更新 更多