开发者

Where does the 'self' come from? Putting a member function as target for threading.Thread

开发者 https://www.devze.com 2023-04-13 06:18 出处:网络
in the following code class foo: def __init__(self,x): self.x = x def do(self): print(self.x) foo1 = foo(1)

in the following code

class foo:
    def __init__(self,x):
        self.x = x

    def do(self):
        print(self.x)

foo1 = foo(1)
foo2 = foo(2)
t1=threading.Thread(target=foo1.do)
t2=threading.Thread(target=foo2.do)
t1.start()
t2.start()

I am using the member function of an instantiated object as target for the thread. I was wondering why it works, i.e. does the threading module do something special to 开发者_如何转开发detect if there is a member function (as opposed to a "normal" function w/o object context) at the other end of the callable-Reference? I think the usual callback mechanism like in ftplib.retrlines() et al will only accept plain global functions. Is it better to stay away from this alltogether?

slarti

PS: coming from C/C++ the exposed behaviour is new to me (although welcome).


You might want to read about Python's method objects.

Python's self is sort of like C++'s this, except you have to put it in the method declaration.

What happens that when you declare a function inside a class, it “becomes” a method. When you get a method of an object, it becomes a bound method, which has the first argument (self) fixed to the object you got it from.

Try:

class Foo(object):
    def do(self):
        print x

instance = Foo()
print Foo.do  # prints <unbound method Foo.do>
print instance.do  # prints <bound method Foo.do of <...>>

# These are equivalent:
Foo.do(instance)
instance.do()

No extra magic is happening in your Threading case, it's just regular Python.


foo1.do and foo2.do are bound methods.

I suggest you look at the following documentation links:

  • http://docs.python.org/library/stdtypes.html#methods (introduction)
  • http://docs.python.org/reference/datamodel.html (in depth)

Excerpt from the second link:

When a bound user-defined method object is called, the underlying function (im_func) is called, inserting the class instance (im_self) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1).


Suppose you wrote the same class in C++:

class foo {
    int x;
  public:
    foo(int x_) { x = x_; }
    void do() { std::cout << x; }
}

foo f = foo(42);

Here &foo::do would be a pointer to member function and you would need a foo instance to be able to call it. Suppose you could pass around f.do: then you wouldn't need anything else to call do() on f. This is exactly what a bound member is in Python and by passing foo1.do you are passing both the method to call and the instance onm which to call it.

This same problem has been addressed in C++ either with proprietary extensions, such as Borland's closures, or with libraries, such as Boost.Bind.


In any instance (non-static) method in a class, the method should be using some variables in the instance of the class thats its running in right? So, every instance method needs a copy the object thats running it to access these variables. That is what self is, a copy of the object thats running the method.

In most languages, its implicitly a parameter in instance methods (so you don't really need to write out self in the method, but its there, but in python its explicitly shown, so you have a parameter calledself` in every instance method. It does not change anything, it's just a sort of more obvious way of showing whats happening.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号