Overriding methods in classes you don't control

Discussion in 'Python' started by Alex VanderWoude, Mar 28, 2005.

  1. Is there a way to override a method on a class whose source you cannot
    change in such a way that you can hook into that method's code? After doing
    some research, it appears that one way to do such a thing is to create a new
    (non-class) method, and then assign the new method to the class in question,
    thus replacing the existing class method. However, I have read vague hints
    in the documentation that this is not a good thing to do (?). Furthermore,
    you probably need access to the source code of the method you are replacing
    so that you can duplicate and modify it in your method. Now in this
    particular case that is true, but what I really want to know is whether or
    not there is an accepted Pythonic way to do this.

    Here's the situation. I'm using wxPython, and I want to make an enhancement
    in the __init__ method of all the frame classes. The ideal place to do this
    is in wxFrame.__init__, since any change there will automatically be
    inherited by the other frame classes (for example, wxMDIParentFrame).
    Obviously I can inherit from wxPython and make the changes in my subclass,
    but then I would have to also subclass wxMDIParentFrame and duplicate my
    enhancements there, and then use only my subclasses rather than the wx***
    classes.

    Basically I want to change wxFrame.__init__ so that it looks sort of like
    this:

    def __init__(self, *args, **kwargs):
    # Some enhancements here.
    # The original code of this method, including the call to its
    ancestor.
    # Some more enhancements here.

    And then I can replace wxFrame's __init__ with my new version by assigning
    it before any frames are instantiated.

    Now I can do this since I have access to the wxPython source code. However,
    I would prefer to have some generalized way of grabbing the original code
    and inserting it where that middle comment is. That way, my enhancements
    will continue to work even with other versions of wxPython (assuming of
    course that my enhancements don't rely on anything in the original code,
    which they don't).

    Or am I barking up the wrong tree entirely?

    - Alex
    Alex VanderWoude, Mar 28, 2005
    #1
    1. Advertising

  2. Alex VanderWoude wrote:
    > Basically I want to change wxFrame.__init__ so that it looks sort of like
    > this:
    >
    > def __init__(self, *args, **kwargs):
    > # Some enhancements here.
    > # The original code of this method, including the call to its
    > ancestor.
    > # Some more enhancements here.
    >
    > And then I can replace wxFrame's __init__ with my new version by assigning
    > it before any frames are instantiated.


    Maybe you can do something like:

    oldinit = wxFrame.__init__
    def newinit(self, *args, **kwargs):
    # Some enhancements here.
    oldinit(self, *args, **kwargs)
    # Some more enhancements here.
    wxFrame.__init__ = newinit

    that is, save the old __init__ method so that it can be accessed from
    within your new __init__ method.

    STeVe
    Steven Bethard, Mar 28, 2005
    #2
    1. Advertising

  3. Alex VanderWoude

    John Roth Guest

    Look up "Aspect Oriented Programming" and Python.
    You should find several packages that can do this,
    together with discussions of how to make cuts and all
    that fun stuff. The feeling of power is very heady - until
    you have to maintain the resulting mess.

    John Roth


    "Alex VanderWoude" <> wrote in message
    news:wgL1e.820524$6l.756354@pd7tw2no...
    > Is there a way to override a method on a class whose source you cannot
    > change in such a way that you can hook into that method's code? After
    > doing
    > some research, it appears that one way to do such a thing is to create a
    > new
    > (non-class) method, and then assign the new method to the class in
    > question,
    > thus replacing the existing class method. However, I have read vague
    > hints
    > in the documentation that this is not a good thing to do (?).
    > Furthermore,
    > you probably need access to the source code of the method you are
    > replacing
    > so that you can duplicate and modify it in your method. Now in this
    > particular case that is true, but what I really want to know is whether or
    > not there is an accepted Pythonic way to do this.
    >
    > Here's the situation. I'm using wxPython, and I want to make an
    > enhancement
    > in the __init__ method of all the frame classes. The ideal place to do
    > this
    > is in wxFrame.__init__, since any change there will automatically be
    > inherited by the other frame classes (for example, wxMDIParentFrame).
    > Obviously I can inherit from wxPython and make the changes in my subclass,
    > but then I would have to also subclass wxMDIParentFrame and duplicate my
    > enhancements there, and then use only my subclasses rather than the wx***
    > classes.
    >
    > Basically I want to change wxFrame.__init__ so that it looks sort of like
    > this:
    >
    > def __init__(self, *args, **kwargs):
    > # Some enhancements here.
    > # The original code of this method, including the call to its
    > ancestor.
    > # Some more enhancements here.
    >
    > And then I can replace wxFrame's __init__ with my new version by assigning
    > it before any frames are instantiated.
    >
    > Now I can do this since I have access to the wxPython source code.
    > However,
    > I would prefer to have some generalized way of grabbing the original code
    > and inserting it where that middle comment is. That way, my enhancements
    > will continue to work even with other versions of wxPython (assuming of
    > course that my enhancements don't rely on anything in the original code,
    > which they don't).
    >
    > Or am I barking up the wrong tree entirely?
    >
    > - Alex
    >
    >
    >
    John Roth, Mar 28, 2005
    #3
  4. Alex VanderWoude

    runsun pan Guest

    Some untested idea:

    1. find what is the base class of wxPython
    2. x= subclass from that base class
    3. make wxPython.__base__ = x

    Don't know if this works, but this is what I would try if I were u
    ('cos its ease).
    runsun pan, Mar 28, 2005
    #4
  5. Alex VanderWoude

    Guest

    I've also come across several situations where modifying existing
    classes seems the simplest and most intuitive thing to do.

    Obviously it is fine for quick hacks but people tend to go 'whoooooo'
    and wave their fingers around when people suggest it as a general
    technique.

    Has anyone got any experience of doing this on medium-size projects and
    how quickly things descend into an unmaintainable mess?

    What are the specific problems and can they be avoided/worked around?

    I suppose the main thing is the problems it causes for other people
    reading your source code i.e. how are they supposed to know that Class
    X now has some of your code injected into it. And thinking about it.
    How are you supposed to remember 3 months down the line!

    Maybe a 'best practises' system where any such modifications were made
    or mentioned right at the start of the source tree or in a distinctly
    named module could alleviate this?

    runsun pan wrote:
    > Some untested idea:
    >
    > 1. find what is the base class of wxPython
    > 2. x= subclass from that base class
    > 3. make wxPython.__base__ = x
    >
    > Don't know if this works, but this is what I would try if I were u
    > ('cos its ease).
    , Mar 28, 2005
    #5
  6. Alex VanderWoude

    runsun pan Guest

    good point, andy.
    runsun pan, Mar 28, 2005
    #6
  7. Alex VanderWoude a écrit :
    > Here's the situation. I'm using wxPython, and I want to make an enhancement
    > in the __init__ method of all the frame classes. The ideal place to do this
    > is in wxFrame.__init__, since any change there will automatically be
    > inherited by the other frame classes (for example, wxMDIParentFrame).
    > Obviously I can inherit from wxPython and make the changes in my subclass,
    > but then I would have to also subclass wxMDIParentFrame and duplicate my
    > enhancements there, and then use only my subclasses rather than the wx***
    > classes.
    >
    > Basically I want to change wxFrame.__init__ so that it looks sort of like
    > this:
    >
    > def __init__(self, *args, **kwargs):
    > # Some enhancements here.
    > # The original code of this method, including the call to its
    > ancestor.
    > # Some more enhancements here.
    >
    > And then I can replace wxFrame's __init__ with my new version by assigning
    > it before any frames are instantiated.


    Sorry, but this won't work with wxPython.
    wxPython classes are just wrappers around C++ classes.

    You may well replace wxFrame.__init__ with your own method, but it won't
    be called by wxMDIParentFrame: wxMDIParentFrame.__init__ directly calls
    the C++ constructor, completely ignoring wxFrame.__init__.
    The call to the superclass' constructor is done in C++.

    Since replacing C++ method is much more difficult (if possible at all),
    I'm afraid you will have to do the replacement you plan for every
    derived class.

    Amaury.
    Amaury Forgeot d'Arc, Mar 30, 2005
    #7
  8. Alex VanderWoude a écrit :
    > Here's the situation. I'm using wxPython, and I want to make an enhancement
    > in the __init__ method of all the frame classes. The ideal place to do this
    > is in wxFrame.__init__, since any change there will automatically be
    > inherited by the other frame classes (for example, wxMDIParentFrame).
    > Obviously I can inherit from wxPython and make the changes in my subclass,
    > but then I would have to also subclass wxMDIParentFrame and duplicate my
    > enhancements there, and then use only my subclasses rather than the wx***
    > classes.
    >
    > Basically I want to change wxFrame.__init__ so that it looks sort of like
    > this:
    >
    > def __init__(self, *args, **kwargs):
    > # Some enhancements here.
    > # The original code of this method, including the call to its
    > ancestor.
    > # Some more enhancements here.
    >
    > And then I can replace wxFrame's __init__ with my new version by assigning
    > it before any frames are instantiated.


    Sorry, but this won't work with wxPython.
    wxPython classes are just wrappers around C++ classes.

    You may well replace wxFrame.__init__ with your own method, but it won't
    be called by wxMDIParentFrame: wxMDIParentFrame.__init__ directly calls
    the C++ constructor, completely ignoring wxFrame.__init__.
    The call to the superclass' constructor is done in C++.

    Since replacing C++ method is much more difficult (if possible at all),
    I'm afraid you will have to do the replacement you plan for every
    derived class.

    Amaury.
    Amaury Forgeot d'Arc, Mar 30, 2005
    #8
    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. Mad Scientist Jr
    Replies:
    2
    Views:
    5,262
    Mad Scientist Jr
    Jun 29, 2004
  2. Jacques-Henri
    Replies:
    1
    Views:
    327
    Michael Borgwardt
    Apr 16, 2004
  3. ankur
    Replies:
    3
    Views:
    328
    ankur
    Aug 10, 2008
  4. Jason
    Replies:
    0
    Views:
    179
    Jason
    Jul 6, 2004
  5. Kenneth McDonald
    Replies:
    5
    Views:
    297
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page