Call a class A method from a class B instance? Do I miss something?

jfong at ms4.hinet.net jfong at ms4.hinet.net
Fri Aug 18 03:22:04 EDT 2017


Ian於 2017年8月18日星期五 UTC+8上午10時41分44秒寫道:
> On Thu, Aug 17, 2017 at 6:03 PM,  <jfong at ms4.hinet.net> wrote:
> > I study some codes of a tutorial about tkinter (https://github.com/daleathan/widget-tour-py3) and can't figure out how it works.
> >
> > Below is the codes from its two major files:
> > ----------------------------
> > # file infrastructure.py
> > ...
> > ...
> > class callit:
> >     def __init__(self, function, *args ):
> >         self.f = function
> >
> >         self.args = args
> >
> >
> >     def __call__(self, *ignored):
> >         self.f(*self.args)
> >
> > ...
> >
> > ------------------------
> > # file widget.py
> > ...
> > from infrastructure import *
> > ...
> > class DemoMainWindow(Frame):
> >     ...
> >     def _fill_textarea(self):
> >         ...
> >         # bind events
> >         self.text.tag_bind(tag, '<Any-Enter>',
> >
> >              callit(self.demoenter_callback, tag) )
> >         ...
> >
> >     def demoenter_callback(self, tag):
> >         ...
> >         self.text.configure(cursor='hand2')
> >         ...
> >
> > ----------------------
> > My question is that the object which was left by callit(self.demoenter_callback, tag) is a callit instance, and the method it calls is a DemoMainWindow's method.
> > How it is possible?
> 
> Methods are just functions with a bit of magic [1] that binds the self
> argument to them.
> 
> DemoMainWindow.demoenter_callback is an unbound method object
> (although in Python 3, it's just an ordinary function). When
> self.demoenter_callback is evaluated, the result is not the same
> unbound method object. Instead you get a different *bound* method
> object, which binds the self argument to the DemoMainWindow instance.
> The important point is that this binding happens when
> self.demoenter_callback is evaluated, not when the method is called.
> 
> This bound method object gets passed to the callit object, which saves
> it as self.f. Later, it calls self.f() which calls the method that is
> still bound to the same DemoMainWindow instance. Note that evaluating
> self.f does not *rebind* the method object. Bound method objects never
> get rebound; they are only created from unbound methods.
> 
> So when self.f() is called the bound DemoMainWindow instance is used
> as the value of the self argument. The fact that it was actually
> called from a method of callit doesn't matter.
> 
> [1] This magic is called the descriptor protocol, and if you want to
> play with it you can use it to create your own method types! This is a
> topic usually presented to intermediate-level Python programmers.

Thank you for your explaination about the bound/unbound method. I had read them in various document many times before but never pay attention to it becasue it seems didn't matter much in real world coding. 

>The important point is that this binding happens when
>self.demoenter_callback is evaluated, not when the method is called.

All I had learned about the "self" argument is that it's a hidden argument and was passed as the first argument at the time when method was called, never though it can be used to "bind" a method alone. It's completely new to me.

>So when self.f() is called the bound DemoMainWindow instance is used
>as the value of the self argument. The fact that it was actually
>called from a method of callit doesn't matter.

It seems there is a hard homework waiting for me. Any hint?

--Jach



More information about the Python-list mailing list