在带有装饰器的__init__之后注入函数调用 [英] Injecting function call after __init__ with decorator

查看:119
本文介绍了在带有装饰器的__init__之后注入函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到创建执行以下操作的类装饰器的最佳方法:

I'm trying to find the best way to create a class decorator that does the following:


  1. 将一些函数注入到装饰类

  2. 在装饰类的 __ init __ 被调用之后,强制调用其中一个函数

  1. Injects a few functions into the decorated class
  2. Forces a call to one of these functions AFTER the decorated class' __init__ is called

当前,我只是保存了对原始 __ init __ 方法的引用,并将其替换为 __ init __ 调用原始函数和附加函数。它看起来类似于这样:

Currently, I'm just saving off a reference to the 'original' __init__ method and replacing it with my __init__ that calls the original and my additional function. It looks similar to this:

orig_init = cls.__init__

def new_init(self, *args, **kwargs):
    """
    'Extend' wrapped class' __init__ so we can attach to all signals
    automatically
    """

    orig_init(self, *args, **kwargs)
    self._debugSignals()

cls.__init__ = new_init

是否有更好的方法来增强原始 __ init __ 或将我的电话插入其他地方?我真正需要的只是在创建对象之后的某个时间调用我的 self._debugSignals()。我也希望它自动发生,这就是为什么我认为 __ init __ 之后是个好地方。

Is there a better way to 'augment' the original __init__ or inject my call somewhere else? All I really need is for my self._debugSignals() to be called sometime after the object is created. I also want it happen automatically, which is why I thought after __init__ was a good place.

可能值得一提的是该装饰者的一些背景知识。您可以在此处找到完整的代码。装饰器的重点是自动附加到任何PyQt信号并在它们发出时进行打印。当我装饰自己的 QtCore.QObject 子类时,装饰器工作正常,但是我最近一直在尝试自动装饰所有QObject子项

It might be worth mentioning some background on this decorator. You can find the full code here. The point of the decorator is to automatically attach to any PyQt signals and print when they are emitted. The decorator works fine when I decorate my own subclasses of QtCore.QObject, however I've been recently trying to automatically decorate all QObject children.

我想要一个'debug我可以自动打印所有信号的应用程序中的模式,以确保一切正常。我确定这会导致TONS的调试,但是我仍然想看看发生了什么。

I'd like to have a 'debug' mode in the application where I can automatically print ALL signals just to make sure things are doing what I expect. I'm sure this will result in TONS of debug, but I'd still like to see what's happening.

问题是我当前的装饰器版本导致了替换 QtCore.QObject .__ init __ segfault $ c> 。我已经尝试调试它,但是代码都是SIP生成的,我没有太多经验。

The problem is my current version of the decorator is causing a segfault when replacing QtCore.QObject.__init__. I've tried to debug this, but the code is all SIP generated, which I don't have much experience with.

所以,我想知道是否有一个在 __ init __ 之后注入函数调用并希望避免出现段错误的更安全,更Python化的方法。

So, I was wondering if there was a safer, more pythonic way to inject a function call AFTER the __init__ and hopefully avoid the segfault.

推荐答案

基于这篇文章此答案,一种替代方法这是通过自定义元类实现的。如下所示(在Python 2.7中测试):

Based on this post and this answer, an alternative way to do this is through a custom metaclass. This would work as follows (tested in Python 2.7):

# define a new metaclass which overrides the "__call__" function
class NewInitCaller(type):
    def __call__(cls, *args, **kwargs):
        """Called when you call MyNewClass() """
        obj = type.__call__(cls, *args, **kwargs)
        obj.new_init()
        return obj


# then create a new class with the __metaclass__ set as our custom metaclass
class MyNewClass(object):
    __metaclass__ = NewInitCaller
    def __init__(self):
        print "Init class"
    def new_init(self):
        print "New init!!"

# when you create an instance
a = MyNewClass()
>>> Init class
>>> New init!!

基本思想是:


  1. 在调用 MyNewClass()时,它搜索元类,发现您已定义 NewInitCaller

  1. when you call MyNewClass() it searches for the metaclass, finds that you have defined NewInitCaller

将调用元类 __ call __ 函数。

此函数使用 type MyNewClass 实例c>,

This function creates the MyNewClass instance using type,

实例运行自己的 __ init __ (打印 Init类)。

The instance runs its own __init__ (printing "Init class").

然后,元类调用实例的 new_init 函数。

The meta class then calls the new_init function of the instance.

这篇关于在带有装饰器的__init__之后注入函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆