【问题标题】:How to access the subclasses of a class as properties?如何将类的子类作为属性访问?
【发布时间】:2012-08-05 03:21:28
【问题描述】:

所以我有一个 .py 文件,其中包含一个可以作为属性访问其子类的类。所有这些子类都是预先定义的。我还需要所有子类都具有相同的能力(让它们自己的子类可以作为属性访问)。我一直面临的最大问题是我不知道如何在我的__getattr__() 实现中访问当前类,所以这是一个很好的起点。

这是我迄今为止尝试过的一些 Python+伪代码。我很确定它不会起作用,因为__getattr__() 似乎只适用于类的实例。如果是这种情况,对不起,我对 Python 中的 OOP 并不像我希望的那样熟悉。

class A(object):
    def __getattr__(self, name):
        subclasses = [c.__name__ for c in current_class.__subclasses__()]
        if name in subclasses:
            return name
    raise AttributeError

【问题讨论】:

  • 如果我们能看到一些代码……或者至少是伪代码示例。
  • 鉴于我提到的问题,我几乎没有代码,一个解决方案也不应该有太多行。不过我会试一试的
  • 具体来说,向我们展示“其子类可以作为属性访问”的代码。

标签: python class properties getattr


【解决方案1】:
>>> class A(object):
...     pass
...
>>> foo = A()
>>> foo.__class__
<class '__main__.A'>

【讨论】:

    【解决方案2】:
        class A(object):
            def __getattr__(self, key):
                for subclass in self.__class__.__subclasses__():
                    if (subclass.__name__ == key):
                        return subclass
                raise AttributeError, key
    

    出于好奇,这是为了什么而设计的?

    【讨论】:

      【解决方案3】:

      如果我正确理解了您的问题,您可以使用自定义元类来做您想做的事情,该元类将classmethod 添加到其实例中。这是一个例子:

      class SubclassAttributes(type):
          def __getattr__(cls, name):  # classmethod of instances
              for subclass in cls.__subclasses__():
                  if subclass.__name__ == name:
                      return subclass
              else:
                  raise TypeError('Class {!r} has no subclass '
                                  'named {!r}'.format(cls.__name__, name))
      
      class Base(object):
          __metaclass__ = SubclassAttributes  # Python 2 metaclass syntax
      
      #class Base(object, metaclass=SubclassAttributes):  # Python 3 metaclass syntax
      #    """ nothing to see here """
      
      class Derived1(Base): pass
      class Derived2(Base): pass
      
      print(Base.Derived1)  # -> <class '__main__.Derived1'>
      print(Base.Derived2)  # -> <class '__main__.Derived2'>
      print(Base.Derived3)  # -> TypeError: Class 'Base' has no subclass named 'Derived3'
      

      对于在 Python 2 和 3 中都有效的东西,定义如下所示的类。从具有 SubclassAttributes 作为其元类的类派生 Base。这类似于six 模块的with_metaclass() 函数的作用:

      class Base(type.__new__(type('TemporaryMeta', (SubclassAttributes,), {}),
                              'TemporaryClass', (), {})): pass
      

      【讨论】:

      • @Felix:我很想听听你这样做的目的。谢谢。
      • 我在 python 中使用这种作为枚举的实现和它们自己的函数
      • @Felix:嗯......听起来很有趣的想法。如果性能是一个问题,您也许可以使用某种记忆技术来避免__getattr__() 在每次访问时通过__subclasses__() 列表进行线性搜索。
      猜你喜欢
      • 2023-02-04
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 2013-03-24
      • 2019-04-02
      • 2012-06-19
      • 2021-10-21
      相关资源
      最近更新 更多