简体   繁体   中英

Python events and delegates

This is probably a basic question but I am new to programming. I am working with a third party python code and it provides a class with event and event delegates. The syntax for the events and event delegates are follows:

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

    public Event RequestEvent As MDNPRequest.RequestEventDelegate 

I wrote the following code to subcribe to the event but is not working. I do not know what I am doing wrong.

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

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

I am adding the two lines of code to the end of a function that opens up the communication channel. I also tested adding the two lines of code to a function that send a poll on the communication channel. In the second scenario the event fires and every time I execute the polling function. Does this defeat the purpose of event subscription?


I think that my problem maybe due to different functions creating instances of the same class. I would like to consolidate some of the functions into a class using the outline shown below. Method1 creates an instance 'a' of a class1 that I would like the other methods in myClass to use. I tried using a class variable which I set to a class1 instance but this is not working. I reference the class variable using the class name for example myClass.variable.somemethod from class1 but I get "Object reference not set to an instance of an object" error. What is the best approach so that all methods in myClass can have access to a? Eventually I would like to call myClass from another module.

    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
          ...

If this is actually your code:

Mreq.RequestEvent += Mreq.RequestEventDelegate(handleResponseEvent)

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

handleResponseEvent is not the same thing as handleRequestEvent .


As a side note, you almost never need to create an explicit delegate. It's sometimes a useful optimization, but it's one more thing you can get wrong, and one more thing that can disguise useful debugging information when you do, so it's usually simpler to write the code without it first, and only add wrap it as a delegate after it's working, if you find yourself creating a whole lot of them and want to save some memory.

From your later edits, I suspect that you're missing the fundamentals of how classes work in Python. You may want to read through the tutorial chapter , or maybe search for a friendlier/more detailed tutorial.

In particular:

I would like to consolidate some of the functions into a class using the outline shown below. Method1 creates an instance 'a' of a class1 that I would like the other methods in myClass to use. I tried using a class variable which I set to a class1 instance but this is not working.

That's not the way to do it. Class attributes, like your class_variable , are created at class creation time (that is, generally, as soon as you import the module or run the script), not instance creation time. If you want something created when instances of your class are created, you use instance attributes, not class attributes, and you set them in the __init__ method. In your case, you don't want the instance created until Method1 is called on an instance—again, that means you use an instance attribute; you just do it inside Method1 rather than __init__ .

Also, class attributes are shared by all instances of the class; instance attributes, each instance has its own one. Thing about dogs: each dog has its own tail, there's not one tail shared by all dogs, so tail is an instance attribute. Often, in simple scripts, you don't notice the difference, because you only happen to ever create one instance of the class. But if you can't figure out the difference practically, think about it conceptually (like the Dog example)—and if you still can't figure it out, you almost always want an instance attribute.

I reference the class variable using the class name for example myClass.variable.somemethod from class1 but I get "Object reference not set to an instance of an object" error.

Most likely this is because class1 is a COM/interop or .NET class, and you're trying to create and use it before doing any of the relevant setup, which is only happening because you're trying to do it as soon as you import the module/run the script. If so, if you create it when you actually intended to, there won't be a problem.

What is the best approach so that all methods in myClass can have access to a?

Create an instance attribute in Method1 , like this:

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

And then use it the same way:

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

Just doing a = whatever just creates a local variable that goes away at the end of the method. Even if it happens to have the same name as a class attribute, instance attribute, or global, you're still creating a new local variable, not modifying the thing you want to modify. Unlike some other languages, Python requires you to be explicit about what you're trying to overwrite— self.a for an instance attribute, myClass.a for a class attribute, etc.—so you don't do it by accident.

Also, note the parentheses at the end of that last expression. If you want to call a function or method, you need parentheses; otherwise, you're just referencing the method itself as a value.


Eventually I would like to call myClass from another module.

I'm not sure what you mean by "class myClass". When you call a class, that constructs a new instance of the class. You can then call that instance's methods the same way you would any other object. It doesn't matter what module it was defined in (except that you obviously have to write my_instance = mymodule.MyClass() ).

Look at how you use the standard library; it's exactly the same. For example, if you import csv , you can construct a DictWriter by writing my_writer = csv.DictWriter(my_file) . And then you call its methods by writing my_writer.writerow(my_row) . Once you've constructed it, it doesn't matter what module it came from.


One more thing:

You've tried to define a class like this:

myClass:

You obviously can't do that; you need the class keyword. But also, in Python 2.x, you always want to give base classes, using object if you don't need anything else. Otherwise, you get an old-style class, which causes all kinds of weird quirks and limitations that you don't want to learn about and have to debug. So:

class myClass(object):

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM