【问题标题】:Get Outer Class Name for Nested Class (Python)获取嵌套类的外部类名称(Python)
【发布时间】:2016-10-21 09:45:23
【问题描述】:

背景

(可能是相关的,因为可能有更简单的方法来实现我想要的。)

我想构建一种声明方式来定义可以由静态代码分析工具分析的“方面”。整个概念写下来here。每个方面(比如Redundancy)可能有递归的子方面(比如Redundancy.Clone),并且每个方面都应该有文档和任意其他属性。用户应该能够选择要分析的方面,如果它是用户选择的方面,我必须以编程方式找出一个方面的内部表示(即对于给定的类Redundancy.Clone我想验证它属于给定字符串redundancy.clone,但不是redundancy.unused_import)。

我决定使用这样的类:

class Redundancy(Aspect):
    """
    This meta aspect describes any kind of redundancy in your source code.
    """

    # Can't inherit from Redundancy here because of the recursion
    class Clone(Aspect):
        """
        This redundancy describes a code clone. Code clones are different pieces of
        code in your codebase that are very similar.
        """

        # Stuff...

问题

对于给定的 Aspect 类,我想获取描述字符串 (Redundancy.Clone -> redundancy.clone)。为此,我必须获取周围模块/类的名称/无论它是什么,检查它是否是一个类(微不足道的)并从中构造一个字符串。

可能的解决方案及其失败的原因

我确实尝试查看我的班级的dir,看看我可以使用的dunder方法中是否有任何有用的东西,但除了repr之外什么也没找到,在上述情况下,<class 'coalib.bearlib.aspects.Redundancy.Clone'>住在@ 987654334@ 模块。这表明它应该是可能的,但我不知道repr 是如何获取这些信息的,我想避免使用repr 并剥离不需要的东西,因为这是一种黑客行为。

我无法从外部继承嵌套类,因为它还没有完全定义。我希望它们嵌套起来以提高可用性,能够from ... import Redundancy 并在我的源代码中写入Redundancy.Clone 是一个巨大的优势。

任何建议,包括改变我的方法,都将不胜感激。

【问题讨论】:

  • 嵌套类在 Python 中非常很少有用。冗余本身有什么作用吗?如果不是,它可能只是一个模块。
  • 让他们有一个继承自 Aspect 的类很好,因为我们可以为它提供与它的“存在”相关的能力,例如它允许定义我们可以进行操作的设置。
  • (哎呀,输入已经发送...)这仍然应该递归工作,例如Redundancy.Clone.FullClone 或诸如此类。要求是: - 方面本身应该很容易编写 - 使用起来应该很直观(如Redundancy.Clone) - 我需要能够获得所描述的字符串表示(这可能很复杂,但不是由用户完成的)

标签: python class python-3.x nested


【解决方案1】:

你可以使用__qualname__ (PEP 3155)

>>> class C:
...   def f(): pass
...   class D:
...     def g(): pass
...
>>> C.__qualname__
'C'
>>> C.f.__qualname__
'C.f'
>>> C.D.__qualname__
'C.D'
>>> C.D.g.__qualname__
'C.D.g'

【讨论】:

  • 您每天都会学到新东西 - 非常感谢!这似乎正是我们所需要的。
【解决方案2】:

您可以在class Redundancy 语句使用type 类完成其执行后构造该类。例如:

class Aspect:
    pass

class Redundancy(Aspect):    

    @classmethod
    def init(cls):
       cls.make_Clone()

    @classmethod
    def make_Clone(cls):
        def __init__(self):
            print('inside Redundancy.Clone')

        methods = {} 
        methods["__init__"] =  __init__

        cls.Clone = type("{0}.Clone".format(cls.__name__), (Redundancy,), methods )

Redundancy.init()

print(Redundancy.Clone)
print(Redundancy.Clone())
# output:
#   <class '__main__.Redundancy.Clone'>
#   inside Redundancy.Clone
#   <__main__.Redundancy.Clone object at 0x01DCA130>

【讨论】:

  • 确实,感谢您的回复!然而,这使我们的 API 变得复杂,因为用户应该能够轻松地以声明的方式定义这些东西。嵌套类允许我们 - 并且感谢 __qualname__ 我们可以这样做。 (另外我们不支持 python 3.3 及更低版本。)
猜你喜欢
  • 2017-08-27
  • 1970-01-01
  • 2017-01-25
  • 2017-02-07
  • 2020-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多