bend or redirect a class method and then call it again

  • Thread starter Franz Steinhaeusler
  • Start date
F

Franz Steinhaeusler

Hello,

(in wxPython)

I want to redirect the SetStatusText
to an own method (change the text somewhat) and
then call the SetStatusText of wx.Frame.

But I have a little problem of understanding, but I think,
it should be achieved somehow.

the output of "show_status" should be then:
"mytext: hallo"

class MyFrame (wx.Frame):
def show_status(self):
SetStatusText ("hallo")

my_frame = Myframe

Plugin (my_frame)

def Plugin(frame_inst)

#here i want to redirect the setstatustext

setattr(frame_inst, 'SetStatusText', NewStatusText)

def SetStatusText(te,text,nr=0):
super(MyFrame, MyFrame).SetStatusText("mytext: " + te)
#this is erronous

def NewStatusText(s, n, n1= 0):
SetStatusText(s, n, n1)

Is this possible?
How can I get this working?

thank you in advance
 
S

Scott David Daniels

Franz said:
I want to redirect the SetStatusText
to an own method (change the text somewhat) and
then call the SetStatusText of wx.Frame.

You are being a bit informal with what is a method and what is a
function. Your examples don't even parse. I think this informality
may be the source of your problem.
class MyFrame (wx.Frame):
def show_status(self):
SetStatusText ("hallo")
my_frame = Myframe
perhaps you mean:
my_frame = Myframe()
Plugin (my_frame)
def Plugin(frame_inst)
No colon above
#here i want to redirect the setstatustext
setattr(frame_inst, 'SetStatusText', NewStatusText)
You seem to be trying to create a subclass dynamically.
def SetStatusText(te,text,nr=0):
super(MyFrame, MyFrame).SetStatusText("mytext: " + te)
#this is erronous
The super call is being done inside a function, not a class.
Is this possible?
How can I get this working?

Does this address your problem?:

class MyFrame(wx.Frame):
def show_status(self):
SetStatusText("hallo")

def SetStatusText(self, te, text, nr=0):
super(MyFrame, self).SetStatusText("mytext: " + te)

-Scott David Daniels
(e-mail address removed)
 
F

Franz Steinhaeusler

[...]
Does this address your problem?:

class MyFrame(wx.Frame):
def show_status(self):
SetStatusText("hallo")

def SetStatusText(self, te, text, nr=0):
super(MyFrame, self).SetStatusText("mytext: " + te)

thank you,

I was not exact enough.

It was not so easy, because I had to apply the super in a function
and not in the class itself.

but finally i got it to work:

#drFrame is inherited from wx.Frame
#in drFrame there are some calls to SetStatusText



import wx
from drpython import DrFrame

def Plugin(DrFrame):

def SetStatusText(text, col):
if col == 1:
#text.find
ind1 = text.find ("Col: ")
if ind1 > -1:
ind1 += len ("Col: ");
ind2 = text.find (" ", ind1)
nr = int (text [ind1:ind2]) + 1
text = text [:ind1] + str (nr) + text[ind2:]
super(type(DrFrame), DrFrame).SetStatusText(text, col)

def NewStatusText(text, col=0):
SetStatusText(text, col)

setattr(DrFrame, 'SetStatusText', NewStatusText)


Is there a better/simpler/clearer solution?

thank you
 
J

Jeff Shannon

Franz said:
#drFrame is inherited from wx.Frame
#in drFrame there are some calls to SetStatusText

import wx
from drpython import DrFrame

def Plugin(DrFrame):

def SetStatusText(text, col):
#[...]

def NewStatusText(text, col=0):
SetStatusText(text, col)

setattr(DrFrame, 'SetStatusText', NewStatusText)


What's the point of this extra 'NewStatusText' method? You're already
overriding SetStatusText. Without the NewStatusText and the setattr()
call, when someone calls SomePluginObject.SetStatusText(), it will call
your new version rather than the wx.Frame (or DrFrame) version -- that's
the whole point of inheritance. (This is true even when the 'someone'
is the object itself, from within the DrFrame base class. The *only*
way to get the base class version(s) is by explicitly asking for it.)
The extra method and setattr() don't seem to be gaining you anything.

Jeff Shannon
Technician/Programmer
Credit International
 
F

Francesco

[#drFrame is inherited from wx.Frame]
[#in drFrame there are some calls to SetStatusText]

I think, I don't make it clear enough.

in drFrame there are some calls to SetStatusText.
these, I want catch, change some strings, and send it back;
simply said.
What's the point of this extra 'NewStatusText' method? You're already
overriding SetStatusText. Without the NewStatusText and the setattr()
call, when someone calls SomePluginObject.SetStatusText(), it will call
your new version rather than the wx.Frame (or DrFrame) version


but not from drFrame itself; that is the point.

I want:
ALL the calls SetStatusText IN DRFRAME itself should be processed.
-- that's
the whole point of inheritance. (This is true even when the 'someone'
is the object itself, from within the DrFrame base class. The *only*
way to get the base class version(s) is by explicitly asking for it.)
The extra method and setattr() don't seem to be gaining you anything.

these calls (in drFrame), I want to "trick", to go further down one
level, or better said redirect to my own function, change the text,
and use the normal SetStatusText from wx.Frame.


Anyway, thank you.
 
J

Jeff Shannon

Francesco said:
but not from drFrame itself; that is the point.

Unless I'm misunderstanding your intent, then yes, from drFrame itself.

Every Plugin object is also a drFrame object (and a wx.Frame object).
*Every* SetStatusText() call on any such object will use the
most-derived version of SetStatusText(), i.e. the Plugin version. Even
the calls that are part of the drFrame class definition. The *only*
exception to this is if, instead of using self.SetStatusText(), you're
using drFrame.SetStatusText(self, ...) -- in that case, you've
explicitly asked for the drFrame version. But if you have, for example,
something like this:

class drFrame(wx.Frame):
def do_something(self, *args):
# [....]
self.SetStatusText("New Status")

then despite the fact that this is a drFrame method, and doesn't know
anything about the Plugin derived class, it will indeed result in the
Plugin version of SetStatusText() being called. That's the whole
*point* of inheritance.

I can see two cases where what you're doing would have some effect that
doesn't replicate normal method resolution order, and to be honest I
think that using either case is a sign of some very questionable design
decisions and definitely violates the guiding principles of OO and
inheritance. One case would be that there are indeed places where the
drFrame.SetStatusText(self, ...) is explicitly called, and you're trying
to override those explicit requests. This is bad form -- an explicit
request should be honored, because there's probably a real reason for
it. The other case is where you are trying to modify the behavior of
all drFrame instances, including those which are *not* also Plugin
instances.

In both cases, you're doing something magic behind your back. It's much
better to do that kind of stuff up front, where it can be seen. (For
instance, in the second case, simply derive an intermediate class from
drFrame, and then derive Plugin from that. Use the intermediate class
anywhere where you'd currently use drFrame, and you're set.) I would
bet that there's a more straightforward way of accomplishing what you
actually want to do, without resorting to this kind of sleight-of-hand.
(I trust sleight-of-hand in programs about as much as I trust
sleight-of-hand in people who're holding my wallet -- there may be cases
where it's justified and where it can be trusted, but I'm not going to
hand my wallet to just anyone...)

Jeff Shannon
Technician/Programmer
Credit International
 
F

Franz Steinhaeusler

Hello Jeff,
Unless I'm misunderstanding your intent, then yes, from drFrame itself.

Every Plugin object is also a drFrame object (and a wx.Frame object).

No. Plugin is a *function*, which receives a *drFrame object*.
It should have the purpose to "redirect" all the SetStatusText
calls from within drFrame.
*Every* SetStatusText() call on any such object will use the
most-derived version of SetStatusText(), i.e. the Plugin version. Even
the calls that are part of the drFrame class definition. The *only*
exception to this is if, instead of using self.SetStatusText(), you're
using drFrame.SetStatusText(self, ...) -- in that case, you've
explicitly asked for the drFrame version. But if you have, for example,
something like this:

class drFrame(wx.Frame):
def do_something(self, *args):
# [....]
self.SetStatusText("New Status")

then despite the fact that this is a drFrame method, and doesn't know
anything about the Plugin derived class, it will indeed result in the
Plugin version of SetStatusText() being called. That's the whole
*point* of inheritance.

I see.
I can see two cases where what you're doing would have some effect that
doesn't replicate normal method resolution order, and to be honest I
think that using either case is a sign of some very questionable design
decisions and definitely violates the guiding principles of OO and
inheritance. One case would be that there are indeed places where the
drFrame.SetStatusText(self, ...) is explicitly called, and you're trying
to override those explicit requests. This is bad form -- an explicit
request should be honored, because there's probably a real reason for
it. The other case is where you are trying to modify the behavior of
all drFrame instances, including those which are *not* also Plugin
instances.

This I want to achieve.

I betted, that there comes the question of bad design :)
In both cases, you're doing something magic behind your back. It's much
better to do that kind of stuff up front, where it can be seen. (For
instance, in the second case, simply derive an intermediate class from
drFrame, and then derive Plugin from that. Use the intermediate class
anywhere where you'd currently use drFrame, and you're set.) I would
bet that there's a more straightforward way of accomplishing what you
actually want to do, without resorting to this kind of sleight-of-hand.
(I trust sleight-of-hand in programs about as much as I trust
sleight-of-hand in people who're holding my wallet -- there may be cases
where it's justified and where it can be trusted, but I'm not going to
hand my wallet to just anyone...)

Thank you for your extensive explanation and for the tips.

I will think about it again.
 
J

Jeff Shannon

Franz said:
No. Plugin is a *function*, which receives a *drFrame object*.
It should have the purpose to "redirect" all the SetStatusText
calls from within drFrame.

Ah, well, then I *was* misunderstanding -- I'm not sure how I became
convinced that Plugin was a derived class, but convinced I was, and
built all further opinions on top of that false conviction.

I'd say that if you want a function to alter the behavior of all objects
of a particular class, it's probably better to have some sort of flag as
a class variable, and have your function set that flag rather than
rebind a method. I'd still be inclined to think that this should be
done on a per-instance basis, rather than for the entire class, but I
can see some case to be made for changing the entire class, too.

Perhaps you can define a StatusTextFormat attribute on drFrame, and have
drFrame.SetStatusText() apply that format to all text before feeding it
to wx.Frame.SetStatusText(). Plugin() would then change this
StatusTextFormat. You could implement this as either a function to be
called, or use % string formatting...

Jeff Shannon
Technician/Programmer
Credit International
 
F

Francesco

Ah, well, then I *was* misunderstanding -- I'm not sure how I became
convinced that Plugin was a derived class, but convinced I was, and
built all further opinions on top of that false conviction.

I'd say that if you want a function to alter the behavior of all objects
of a particular class, it's probably better to have some sort of flag as
a class variable, and have your function set that flag rather than
rebind a method. I'd still be inclined to think that this should be
done on a per-instance basis, rather than for the entire class, but I
can see some case to be made for changing the entire class, too.

Perhaps you can define a StatusTextFormat attribute on drFrame, and have
drFrame.SetStatusText() apply that format to all text before feeding it
to wx.Frame.SetStatusText(). Plugin() would then change this
StatusTextFormat. You could implement this as either a function to be
called, or use % string formatting...


thank you again for your answer.
I have to think about it.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top