【问题标题】:Do something automatically after class definition?类定义后自动做某事?
【发布时间】:2013-06-13 06:45:14
【问题描述】:

我想要的是以下内容:

lst = []

class Awesome:
  """This is my magical super class."""

  ...

class Inherits(Awesome):
  """Awesome does awesome stuff with Inherits."""
  name = "Stack"

class InheritsAgain(Awesome):
  name = "Overflow"

print(lst)
#: ['Stack', 'Overflow']

所以基本上,当定义 InheritsInheritsAgain 类时,因为它们 从Awesome 继承,Awesome 有一些元类魔法(或其他),读取 来自继承类的属性name,并将其附加到lst

我查看了 Python 中的元类,但我不确定它们究竟如何组合在一起。

这在 Python 中可行吗?如果是,你会怎么做?

编辑:

让我们添加到上面的示例中,这样它也可以工作:

class AndAgain(Awesome):
  name = "/root/path/<name>/<id>"

  def go():
    pass

我希望定义整个类AndAgain,这样我可以检查并看到name 存在,其值为"/root/path/&lt;name&gt;/&lt;id&gt;",并且函数go() 也存在。

【问题讨论】:

  • 我觉得有必要说让一个类依赖/操作一个全局变量是不可移植的,如果你的项目变得太大可能会让人困惑。
  • 这比我最初想象的要复杂。你确定你必须那样做吗?这不能是XY Problem 的一个实例吗?
  • 全局变量只是一个例子。 ;-) 我希望你不要以为我真的会像我那样为我的课程命名。实际应用程序是一种自动添加 REST API 端点的方法。如果我不必总是写api.add_resource(ClassName, "/location"),那会很好。

标签: python-3.x metaprogramming


【解决方案1】:
lst = []

class AwesomeMeta(type):
    def __new__(metacls, cls, bases, classdict):
        if cls != 'Awesome':
            lst.append(cls)
        return super().__new__(metacls, cls, bases, classdict)

class Awesome(metaclass=AwesomeMeta):
  """This is my magical super class."""


class Stack(Awesome):
  """Awesome does awesome stuff with Inherits."""


class Overflow(Awesome):
    """More awesomely stuff!"""

print(lst)

并显示在班级内部:

lst = []

class AwesomeMeta(type):
    def __new__(metacls, cls, bases, classdict):
        if 'name' in classdict:
            lst.append(classdict['name'])
        return super().__new__(metacls, cls, bases, classdict)

class Awesome(metaclass=AwesomeMeta):
    """This is my magical super class."""


class Inherits(Awesome):
    """Awesome does awesome stuff with Inherits."""

    name = 'Stack'


class InheritsAgain(Awesome):
    """More awesomely stuff!"""

    name = 'Overflow'

class AndAgain(Awesome):
    name = "/root/path/<name>/<id>"

    def go():
        pass

print(lst)

【讨论】:

  • 也许我使用属性名称的简单示例误导了我。我想要的是任意的东西,比如我可以从子类中提取的正则表达式模式。
  • @cassava:完全没有——这给了你工具;在元类__new__ 中添加您想要/需要的任何内容,以检查正在创建的类并对其进行修改或其他任何内容。
  • 我假设你的意思是class Awesome(object)Awesome真的需要继承object吗?不是所有东西都隐式继承object吗?
  • @cassava:您没有将问题标记为 Python3,所以我编写了 Python 2 代码。 :) 在 Python 2 中,并非所有内容都继承自对象。而且,我的意思是class Awesome(object)。 :)
【解决方案2】:

可以使用元类

class AwesomeMeta(type):
    lst = []
    def __new__(metacls, cls, bases, classdict):
        if 'name' in classdict:
            metacls.lst.append(classdict['name'])
        return super(AwesomeMeta, metacls).__new__(metacls, cls, bases, classdict)

class Awesome(object):
    """This is my magical super class."""
    __metaclass__ = AwesomeMeta


class Inherits(Awesome):
    """Awesome does awesome stuff with Inherits."""
    name = 'Stack'


class InheritsAgain(Awesome):
    """More awesomely stuff!"""
    name = 'Overflow'

print InheritsAgain.lst, Inherits.lst, Awesome.lst

或者可以使用__subclasses__方法

print [i.name for i in Awesome.__subclasses__()]

或者可以使用类装饰器

lst = []
def cls_decorator(cls):
    lst.append(cls.name)
    return cls

@cls_decorator
class Awesome(object):
    """This is my magical super class."""
    name = 'Awesome'


@cls_decorator
class Inherits(Awesome):
    """Awesome does awesome stuff with Inherits."""
    name = 'Stack'


@cls_decorator
class InheritsAgain(Awesome):
    """More awesomely stuff!"""
    name = 'Overflow'

解决方案应该取决于你要做什么

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 2018-04-09
    • 2012-09-22
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 2020-10-27
    • 2016-05-18
    相关资源
    最近更新 更多