【问题标题】:Python events and delegatesPython 事件和委托
【发布时间】:2013-09-20 01:53:17
【问题描述】:

这可能是一个基本问题,但我是编程新手。我正在使用第三方 python 代码,它提供了一个带有事件和事件委托的类。事件和事件委托的语法如下:

    public Delegate Sub RequestEventDelegate (request As MDNPRequest, _
      response as MDNPResponseParser)

    public Event RequestEvent As MDNPRequest.RequestEventDelegate 

我编写了以下代码来订阅该事件,但无法正常工作。我不知道我是什么 做错了。

    Mreq = MDNPRequest()
    Mreq.RequestEvent += Mreq.RequestEventDelegate(handleResponseEvent)

    def handleResponseEvent (request, response):
        print ' event fired'

我将两行代码添加到打开通信通道的函数的末尾。我还测试了将这两行代码添加到在通信通道上发送轮询的函数中。在第二种情况下,事件触发并且每次我执行轮询功能。这是否违背了事件订阅的目的?


我认为我的问题可能是由于不同的函数创建了同一类的实例。我想使用下面显示的大纲将一些函数合并到一个类中。 Method1 创建了我希望 myClass 中的其他方法使用的 class1 的实例“a”。我尝试使用我设置为 class1 实例的类变量,但这不起作用。我使用类名引用类变量,例如来自 class1 的 myClass.variable.somemethod 但我得到“对象引用未设置为对象的实例”错误。使 myClass 中的所有方法都可以访问 a 的最佳方法是什么?最终我想从另一个模块调用 myClass 。

    from file1 import *

    myClass:

       class_variable = class1() # class1 from file1

       def __init__(self)
       ...

       def Method1(self, argument list):
         # this method instantiates a  
          ...
          a = class1() 

       def Method2 (self):
          ...
          a.class1method1
          ...

       def Method3 (self):
          ...
          a.class1method2
          ...

【问题讨论】:

  • 这是 IronPython 和您尝试匹配的 C# 语法吗?还是有什么不同?
  • @abarnert 我正在尝试匹配 VB。
  • 谢谢。一般来说,将这些信息放在问题中会有所帮助——更重要的是,放置一个指向信息来源的链接。在这种情况下,这些都可能与您的问题无关,但它永远不会受到伤害。
  • “我认为我的问题可能是由于不同的函数创建了同一类的实例。”这应该不是问题,除非您只在一个实例上注册事件,而不是所有事件,或类似的东西。没有看到你的代码,我不知道你是不是。更一般地说,如果您向我们展示足以证明您的问题的 SSCCE,您将更容易找到您做错的地方,而不必猜测您可能做错了什么。
  • 另外,在您最新的代码中,您只是引用了方法(例如,a.class1method);你永远不会在任何地方给他们打电话 (a.class1method())。如果在您的真实代码中也是如此,它可以很容易地解释为什么事情没有按您预期的方式工作。

标签: python class events methods delegates


【解决方案1】:

如果这实际上是您的代码:

Mreq.RequestEvent += Mreq.RequestEventDelegate(handleResponseEvent)

def handleRequestEvent (request, response):
    print ' event fired'

handleResponseEventhandleRequestEvent 不同。


附带说明,您几乎不需要创建显式委托。它有时是一个有用的优化,但它是你可能会出错的另一件事,也是另一件事可以在你这样做时伪装有用的调试信息,所以通常在没有它的情况下编写代码更简单,并且只将它添加为委托在它工作之后,如果你发现自己创建了很多它们并想节省一些内存。

【讨论】:

    【解决方案2】:

    从您后来的编辑中,我怀疑您缺少 Python 中类如何工作的基础知识。您可能想通读the tutorial chapter,或者搜索更友好/更详细的教程。

    特别是:

    我想使用下面显示的大纲将一些函数合并到一个类中。 Method1 创建了我希望 myClass 中的其他方法使用的 class1 的实例“a”。我尝试使用我设置为 class1 实例的类变量,但这不起作用。

    这不是这样做的方法。类属性,如您的 class_variable,是在类创建时创建的(也就是说,通常,只要您 import 模块或运行脚本),而不是实例创建时。如果您希望在创建类的实例时创建某些内容,则使用实例属性,而不是类属性,并在 __init__ 方法中设置它们。在您的情况下,您不希望在实例上调用 Method1 之前创建实例 - 同样,这意味着您使用实例属性;您只需在 Method1 内部进行操作,而不是在 __init__ 内部进行。

    此外,类的所有实例都共享类属性;实例属性,每个实例都有自己的。关于狗:每条狗都有自己的尾巴,并不是所有的狗都共用一条尾巴,所以tail是一个实例属性。通常,在简单的脚本中,您不会注意到差异,因为您只碰巧创建了一个类的实例。但是,如果您无法在实践中找出差异,请从概念上考虑它(例如 Dog 示例)——如果您仍然无法弄清楚,您几乎总是需要一个实例属性。

    我使用类名来引用类变量,例如来自 class1 的 myClass.variable.somemethod,但我得到“对象引用未设置为对象的实例”错误。

    这很可能是因为class1 是一个 COM/interop 或 .NET 类,并且您在进行任何相关设置之前尝试创建和使用它,这只是因为您尝试这样做只要您import 模块/运行脚本,它就可以了。如果是这样,如果您按照实际意图创建它,就不会有问题。

    让 myClass 中的所有方法都可以访问 a 的最佳方法是什么?

    Method1中创建一个实例属性,像这样:

    def Method1(self, argument list):
        # this method instantiates a  
         ...
        self.a = class1() 
    

    然后以同样的方式使用它:

    def Method2 (self):
         ...
        self.a.class1method1()
         ...
    

    只是做a = whatever 只是创建了一个在方法结束时消失的局部变量。即使它恰好与类属性、实例属性或全局属性同名,您仍在创建一个新的局部变量,而不是修改您要修改的内容。与其他一些语言不同,Python 要求您明确说明您要覆盖的内容——self.a 用于实例属性,myClass.a 用于类属性等——因此您不会意外地这样做。

    另外,请注意最后一个表达式末尾的括号。如果要调用函数或方法,则需要括号;否则,您只是将方法本身作为值引用。


    最终我想从另一个模块调用 myClass。

    我不确定您所说的“class myClass”是什么意思。当您调用一个类时,它会构造该类的一个新实例。然后,您可以像调用任何其他对象一样调用该实例的方法。定义在哪个模块中并不重要(除非您显然必须写 my_instance = mymodule.MyClass())。

    看看你是如何使用标准库的;完全一样。例如,如果你import csv,你可以通过写my_writer = csv.DictWriter(my_file)来构造一个DictWriter。然后你通过写my_writer.writerow(my_row) 来调用它的方法。一旦你构建了它,它来自哪个模块都没有关系。


    还有一件事:

    你试图定义一个这样的类:

    myClass:
    

    你显然不能这样做;你需要class 关键字。而且,在 Python 2.x 中,您总是希望提供基类,如果您不需要其他任何东西,请使用 object。否则,你会得到一个老式的类,这会导致你不想了解并且必须调试的各种奇怪的怪癖和限制。所以:

    class myClass(object):
    

    【讨论】:

    • @abarnet 感谢您的意见。我不知道可以在 init 之外实例化一个类,这就是我尝试使用类变量的原因。我现在正在运行一些测试代码。
    • @CarlosBustamante:“在__init__ 之外实例化一个类”是什么意思?实例化一个类只是 "my_object = myClass()` 部分,它永远不会在 __init__ 中发生。(嗯,它可能发生在某些 other 类的 __init__ 中。)你是说“添加一个实例变量?这往往会让来自 Java 等语言的人感到惊讶。在 Python 中,您可以随时将新变量添加到任何对象(某些内置类型的对象除外)——即使是完全在类之外。
    • @abarnet 我在想实例变量必须在 init 中定义。正如您所指出的,可以随时分配实例变量。
    猜你喜欢
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多