Using globals with classes

M

Madhusudan Singh

Hi

I am relatively new to Python.

I am using Qt Designer to create a UI for a measurement application that I
use.

Everything seems to be clear but the use of globals (defined in the module
that is generated using pyuic, that contains the form class).

I am using qwtplot to display a running plot :

void Form3::runningplot(n,plottitle,xname,x,y1name,y1,y2name,y2)
{
if n==1 :

plotkey1=self.runningqwtPlot.insertCurve(y1name,self.runningqwtPlot.xBottom,self.runningqwtPlot.yLeft)

plotkey2=self.runningqwtPlot.insertCurve(y2name,self.runningqwtPlot.xBottom,self.runningqwtPlot.yRight)
self.runningqwtPlot.setTitle(plottitle)
self.runningqwtPlot.setXGrid(True)
self.runningqwtPlot.setAxisAutoScale(self.runningqwtPlot.yLeft)
self.runningqwtPlot.setAxisAutoScale(self.runningqwtPlot.yRight)
self.runningqwtPlot.setAxisAutoScale(self.runningqwtPlot.xBottom)
self.runningqwtPlot.setAxisTitle(self.runningqwtPlot.yLeft,y1name)
self.runningqwtPlot.setAxisTitle(self.runningqwtPlot.yRight,y2name)
self.runningqwtPlot.setAxisTitle(self.runningqwtPlot.xBottom,xname)
self.runningqwtPlot.setCurveData(plotkey1,x,y1,n)
self.runningqwtPlot.setCurveData(plotkey2,x,y2,n)
self.runningqwtPlot.replot()
else :
self.runningqwtPlot.setCurveData(plotkey1,x,y1,n)
self.runningqwtPlot.setCurveData(plotkey2,x,y2,n)
self.runningqwtPlot.replot()
}

where the above routine is called repeatedly to display real time data.
Now, plotkey1 and plotkey2 need to remain unchanged between successive
invocations of setCurveData() and replot() above. I have defined these as
globals (in the Form settings comment field with Python: as usual).
However, when I run it, I get an error indicating that plotkey1 and
plotkey2 are unknown outside.

I also have a global variable named "globaldebug" that when set to True,
shows some diagnostic information as different slots are called. That too
fails with the same error :

NameError: global name 'globaldebug' is not defined

Is there a way to make a Python function "remember" the values of certain
variables ? Or use fortran 95 like use module, only : varname, type of
within a def ?
 
D

Diez B. Roggisch

Is there a way to make a Python function "remember" the values of certain
variables ? Or use fortran 95 like use module, only : varname, type of
within a def ?

I'm not sure what you are trying to do here - but it seems to me that
you are not properly designing your application. You really shouldn't
use the Designers code-insertion features. The reason is simple: you
the have two tools to write code in instead of one (your editor/IDE).
And you don't make plotkey* global - use instance variables.

So I'm going to describe how I dow work with PyQt:

- I create a Widget in the designer
- compile it using pyuic
- _extend_ it
- write my code in the extended version

So I end up with something like this (I use modules to separate
classes):

ui/plot.ui
ui/plot.py
views/plot.py

where views/plot.py looks like this:

class Plot(ui.plot.Plot):
def __init__(self, *args):
ui.plot.Plot.__init__(self, *args)
self.plotkey1 = <whatever>

def update(self):
# access self.plotkey here



HTH,

DIez
 
D

Diez B. Roggisch

Is there a way to make a Python function "remember" the values of certain
variables ? Or use fortran 95 like use module, only : varname, type of
within a def ?

I'm not sure what you are trying to do here - but it seems to me that
you are not properly designing your application. You really shouldn't
use the Designers code-insertion features. The reason is simple: you
the have two tools to write code in instead of one (your editor/IDE).
And you don't make plotkey* global - use instance variables.

So I'm going to describe how I dow work with PyQt:

- I create a Widget in the designer
- compile it using pyuic
- _extend_ it
- write my code in the extended version

So I end up with something like this (I use modules to separate
classes):

ui/plot.ui
ui/plot.py
views/plot.py

where views/plot.py looks like this:

class Plot(ui.plot.Plot):
def __init__(self, *args):
ui.plot.Plot.__init__(self, *args)
self.plotkey1 = <whatever>

def update(self):
# access self.plotkey here



HTH,

DIez
 
S

Scott David Daniels

Madhusudan said:
.... I am using qwtplot to display a running plot :

void Form3::runningplot(n,plottitle,xname,x,y1name,y1,y2name,y2)
{
^^ I presume this is just some untranslated stuff ^^
if n==1 :

plotkey1=self.runningqwtPlot.insertCurve(y1name,self.runningqwtPlot.xBottom,self.runningqwtPlot.yLeft)

plotkey2=self.runningqwtPlot.insertCurve(y2name,self.runningqwtPlot.xBottom,self.runningqwtPlot.yRight)
self.runningqwtPlot.setTitle(plottitle)
self.runningqwtPlot.setXGrid(True)
self.runningqwtPlot.setAxisAutoScale(self.runningqwtPlot.yLeft)
self.runningqwtPlot.setAxisAutoScale(self.runningqwtPlot.yRight)
self.runningqwtPlot.setAxisAutoScale(self.runningqwtPlot.xBottom)
self.runningqwtPlot.setAxisTitle(self.runningqwtPlot.yLeft,y1name)
self.runningqwtPlot.setAxisTitle(self.runningqwtPlot.yRight,y2name)
self.runningqwtPlot.setAxisTitle(self.runningqwtPlot.xBottom,xname)
self.runningqwtPlot.setCurveData(plotkey1,x,y1,n)
self.runningqwtPlot.setCurveData(plotkey2,x,y2,n)
self.runningqwtPlot.replot()
else :
self.runningqwtPlot.setCurveData(plotkey1,x,y1,n)
self.runningqwtPlot.setCurveData(plotkey2,x,y2,n)
self.runningqwtPlot.replot()
}

The way I'd normally accomplish this is to separate the setup and use
by defining a class:

class CurvePlot(object):
def __init__(self, plot, plottitle, xname, y1name, y2name,
key1=None, key2=None):
self.plot = plot
if key1 is None:
key1 = plot.insertCurve(y1name, plot.xBottom, plot.yLeft)
self.key1 = key1
if key2 is None:
key2 = plot.insertCurve(y2name, plot.xBottom, plot.yRight)
self.key2 = key2
plot.setTitle(plottitle)
plot.setXGrid(True)
plot.setAxisAutoScale(plot.yLeft)
plot.setAxisAutoScale(plot.yRight)
plot.setAxisAutoScale(plot.xBottom)
plot.setAxisTitle(plot.yLeft, y1name)
plot.setAxisTitle(plot.yRight, y2name)
plot.setAxisTitle(plot.xBottom, xname)

def curve(self, x, y1, n)
self.plot.setCurveData(self.key1, x, y1, n)
self.plot.setCurveData(self.key2, x, y2, n)
self.plot.replot()

And then calling it like:

cplot = CurvePlot(self.runningqwtPlot, plottitle,
xname, y1name, y2name)
cplot.curve(n, x, y1, y2)
I also have a global variable named "globaldebug" that when set to True,
shows some diagnostic information as different slots are called. That too
fails with the same error :

NameError: global name 'globaldebug' is not defined
What you probably don't understand is that "globals" are per-module, not
program-wide. If you write a global from inside a function or method,
you need to declare "global varname" inside the function or method in
which you do the writing. Simply using (reading) a global in a module
does not require the "global" declaration.

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

Madhusudan Singh

Many thanks for an excellent solution to the problem and clearing up my mind
about globals.

In some sense, Python globals seem to be a little like the COMMON statement
in the old Fortran 77 standard.
 
M

Madhusudan Singh

Scott said:
The way I'd normally accomplish this is to separate the setup and use
by defining a class:

How would one enable dynamic autoscaling of the axes ?

I am using setAxisAutoScale, and when the application ends, I do get
correctly autoscaled axes, but not while the measurement is in progress.
 
D

Dennis Lee Bieber

In some sense, Python globals seem to be a little like the COMMON statement
in the old Fortran 77 standard.

Not really. Fortran COMMON block were named pages of memory. The
interpretation of that memory was dependent upon the variables declared
to be /in/ the COMMON block. Prior to the capability to in "include"
files, it was quite easy to make a mistake and misalign references to
COMMON.

program main

double precision a_real
integer int_array(5)
float real_2
common /some_common/ a_real, real_2, int_array

-=-=-=-=-=-

subroutine callme

double precision my_real
double precision really_2
integer my_ints(5)
common /some_common/ my_real, really_2, my_ints

-=-=-=-=-=-

a_real and my_real are okay -- same double precision
real_2 and really_2 differ in size; so really_2 is accessing half
its value from what is int_array(1).
int_array array and my_ints are both five elements long... but the
mismatch on really_2 means that my_ints (1..4) align with
int_array(2..5)

Python's "global" statement, when used inside a function/method
basically says "modify the variable defined at the module (aka, file)
level"


--
 

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,770
Messages
2,569,584
Members
45,078
Latest member
MakersCBDBlood

Latest Threads

Top