Re: Ugly modification of a class, can it be done better ?

Discussion in 'Python' started by Jack Diederich, May 21, 2010.

  1. On Thu, May 20, 2010 at 8:13 PM, Stef Mientki <> wrote:
    > hello,
    >
    > This might be a strange question, but as a practical guy, I'm not searching
    > for the best solution, but for a practical solution.
    >
    > I've a class which I've used very extensively.
    > Now I want to extend that class with an action on a double click event, but
    > that action is determined by the main program.
    > Normally I would create an derived class and add that specific action.
    > But I find it too much effort in this specific case, half of the instances
    > need the extension, half of it dont.
    > So I want to change the behavior of the class dynamically.
    > I've done it by adding a global variable (Base_Grid_Double_Click) in the
    > module,
    > initial set to None,
    > but can be changed by the main program to some callback function.
    > (see the code below)
    > Is this a valid construction ( sorry I'm not a programmer),
    > or are there better ways to accomplish similar dynamic behavior ?
    >


    You can have two classes and then just change the class of the
    instances that need it.

    class A(object):
    def method1(self): pass

    class B(A):
    def method2(self): pass

    ob = A()
    # click happens
    ob.__class__ = B

    -Jack
     
    Jack Diederich, May 21, 2010
    #1
    1. Advertising

  2. Sorry for breaking threading, but Stef's original post has not come
    through to me.

    > On Thu, May 20, 2010 at 8:13 PM, Stef Mientki <>
    > wrote:


    >> So I want to change the behavior of the class dynamically. I've done it
    >> by adding a global variable (Base_Grid_Double_Click) in the module,
    >> initial set to None,
    >> but can be changed by the main program to some callback function. (see
    >> the code below)


    How is this supposed to work? If you have *one* global, then *every*
    instance will see the same setting. To change it dynamically, you enter a
    nightmare world of having to save the global, modify it, then restore it,
    every single time. Trust me, I've been there, this is the *worst* way of
    programming. This is why object oriented inheritance was invented, to
    escape this nonsense!

    The first thing is to make the callback specific to the class, not
    global. Why does your printing code need access to the callback that
    handles double-clicking on a grid? It doesn't! So don't give it that
    access (at least, not easy access). Put the callback in the class.

    class MyClass:
    callback = None
    def method(self, *args):
    if self.callback is None:
    behaviour_with_no_callback()
    else:
    behaviour_with_callback()


    Now if you want to apply a callback to some instances, and not others, it
    is totally simple:


    red = MyClass()
    blue = MyClass()
    red.callback = my_callback_function

    and you're done.


    If you have lots of instances that use the same callback? Make a subclass.

    class MyDottedClass(MyClass):
    pass

    red = MyClass()
    blue = MyClass()
    red_with_green_dots = MyDottedClass()
    blue_with_green_dots = MyDottedClass()

    MyDottedClass.callback = dotted_callback

    And now all the dot instances will use the same callback without
    effecting the undotted instances. What to change them all to use a
    different behaviour?

    MyDottedClass.callback = something_different

    and now they all change, again without effecting the undotted instances.




    >> Is this a valid construction ( sorry I'm not a programmer), or are
    >> there better ways to accomplish similar dynamic behavior ?


    Of course you're a programmer! You're writing programs, aren't you?




    --
    Steven
     
    Steven D'Aprano, May 21, 2010
    #2
    1. Advertising

  3. In article <4bf5e19e$0$27861$>,
    Steven D'Aprano <> wrote:
    >Sorry for breaking threading, but Stef's original post has not come
    >through to me.
    >
    >> On Thu, May 20, 2010 at 8:13 PM, Stef Mientki <>
    >> wrote:

    >
    >>> So I want to change the behavior of the class dynamically. I've done it
    >>> by adding a global variable (Base_Grid_Double_Click) in the module,
    >>> initial set to None,
    >>> but can be changed by the main program to some callback function. (see
    >>> the code below)

    >
    >How is this supposed to work? If you have *one* global, then *every*
    >instance will see the same setting. To change it dynamically, you enter a
    >nightmare world of having to save the global, modify it, then restore it,
    >every single time. Trust me, I've been there, this is the *worst* way of
    >programming. This is why object oriented inheritance was invented, to
    >escape this nonsense!
    >
    >The first thing is to make the callback specific to the class, not
    >global. Why does your printing code need access to the callback that
    >handles double-clicking on a grid? It doesn't! So don't give it that
    >access (at least, not easy access). Put the callback in the class.
    >
    >class MyClass:
    > callback = None
    > def method(self, *args):
    > if self.callback is None:
    > behaviour_with_no_callback()
    > else:
    > behaviour_with_callback()
    >
    >
    >Now if you want to apply a callback to some instances, and not others, it
    >is totally simple:
    >
    >
    >red = MyClass()
    >blue = MyClass()
    >red.callback = my_callback_function
    >
    >and you're done.


    Don't go overboard in complication.
    Python can handle variable functions just fine, if that is the
    proper solution to your problem. (In c they are called function
    pointers and they are unruly.)

    def a(b,c): return b+c
    def p(q,r): return q*r
    x=a
    x(3,5)
    8
    x=p
    x(3,5)
    15

    <SNIP>

    >--
    >Steven


    Sorry, but couldn't respond to the original message.
    My newsserver doesn't have it anymore.

    Groetjes Albert

    --
    --
    Albert van der Horst, UTRECHT,THE NETHERLANDS
    Economic growth -- being exponential -- ultimately falters.
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
     
    Albert van der Horst, May 23, 2010
    #3
  4. Jack Diederich

    Stef Mientki Guest

    On 21-05-2010 03:27, Steven D'Aprano wrote:
    > Sorry for breaking threading, but Stef's original post has not come
    > through to me.
    >
    >
    >> On Thu, May 20, 2010 at 8:13 PM, Stef Mientki <>
    >> wrote:
    >>

    >
    >>> So I want to change the behavior of the class dynamically. I've done it
    >>> by adding a global variable (Base_Grid_Double_Click) in the module,
    >>> initial set to None,
    >>> but can be changed by the main program to some callback function. (see
    >>> the code below)
    >>>

    > How is this supposed to work? If you have *one* global, then *every*
    > instance will see the same setting.

    But that's exactly what I need ;-)
    The problem is a little more complicated,
    I've several "frame-works",
    that searches for specific modules (applications) in a specific directory.
    The frame work should determine what should happen (e.g. on a
    doubleclick of a grid cell) in these modules (application),
    but the frame work has no idea what kind of instances are in these modules.
    The same module can be used in different frame-works (or even
    stand-alone) and the behavior of e.g. a doubleclick,
    can differ, depending on the frame work.
    Describing the situation above, I realize that the concept is already
    spaghetti in itself ;-)
    but for a modular system this works like a charm.
    So for the moment I'll stick to the orginal solution.

    thank you all for the responses.
    cheers,
    Stef Mientki

    > To change it dynamically, you enter a
    > nightmare world of having to save the global, modify it, then restore it,
    > every single time. Trust me, I've been there, this is the *worst* way of
    > programming. This is why object oriented inheritance was invented, to
    > escape this nonsense!
    >
    > The first thing is to make the callback specific to the class, not
    > global. Why does your printing code need access to the callback that
    > handles double-clicking on a grid? It doesn't! So don't give it that
    > access (at least, not easy access). Put the callback in the class.
    >
    > class MyClass:
    > callback = None
    > def method(self, *args):
    > if self.callback is None:
    > behaviour_with_no_callback()
    > else:
    > behaviour_with_callback()
    >
    >
    > Now if you want to apply a callback to some instances, and not others, it
    > is totally simple:
    >
    >
    > red = MyClass()
    > blue = MyClass()
    > red.callback = my_callback_function
    >
    > and you're done.
    >
    >
    > If you have lots of instances that use the same callback? Make a subclass.
    >
    > class MyDottedClass(MyClass):
    > pass
    >
    > red = MyClass()
    > blue = MyClass()
    > red_with_green_dots = MyDottedClass()
    > blue_with_green_dots = MyDottedClass()
    >
    > MyDottedClass.callback = dotted_callback
    >
    > And now all the dot instances will use the same callback without
    > effecting the undotted instances. What to change them all to use a
    > different behaviour?
    >
    > MyDottedClass.callback = something_different
    >
    > and now they all change, again without effecting the undotted instances.
    >
    >
    >
    >
    >
    >>> Is this a valid construction ( sorry I'm not a programmer), or are
    >>> there better ways to accomplish similar dynamic behavior ?
    >>>

    > Of course you're a programmer! You're writing programs, aren't you?
    >
    >
    >
    >
    >
     
    Stef Mientki, May 26, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. MooMaster
    Replies:
    11
    Views:
    436
    MooMaster
    Apr 9, 2009
  2. Krekna Mektek
    Replies:
    3
    Views:
    112
  3. Wes Gamble
    Replies:
    3
    Views:
    183
    Wes Gamble
    Aug 12, 2006
  4. James E Keenan
    Replies:
    1
    Views:
    131
    Steve Grazzini
    Oct 14, 2003
  5. Zhidian Du
    Replies:
    0
    Views:
    174
    Zhidian Du
    Feb 21, 2004
Loading...

Share This Page