By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,548 Members | 1,513 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,548 IT Pros & Developers. It's quick & easy.

I thought I'd 'got' globals but...

P: n/a
I thought I had 'got' globals but this one seems strange.
I want my example function 'doIt' to use and optionally modify a module
variable 'gname', so I declare 'global gname' in the function, but when
modified it doesn't stay modified.

gname = 'Sue'
def doIt(name = gname):
global gname
gname = name
print 'doIt name', name, 'gname', gname

print 'start gname', gname
doIt()
doIt(name='Lisa')
doIt()
print 'finish gname', gname

gives...
start gname Sue
doIt name Sue gname Sue
doIt name Lisa gname Lisa
doIt name Sue gname Sue
finish gname Sue

The variable gname has reverted back to value 'Sue'

Curiously though, without the third doIt() call, it works...
print 'start gname', gname
doIt()
doIt(name='Lisa')
#doIt()
print 'finish gname', gname

gives...
start gname Sue
doIt name Sue gname Sue
doIt name Lisa gname Lisa
finish gname Lisa

The variable gname has been modified to 'Lisa'

Any ideas how I can make the 'Lisa' assignment permanent forever in 2nd
doIt? Thanks

(Note. Contrived example substitutes for a web-type app, where, if the
page is called without arguments then it displays the global defaults.
If the page is called with form arguments then it should be able to
change the global defaults)

Jul 6 '06 #1
Share this Question
Share on Google+
17 Replies


P: n/a
meridian wrote:
I thought I had 'got' globals but this one seems strange.
I want my example function 'doIt' to use and optionally modify a module
variable 'gname', so I declare 'global gname' in the function, but when
modified it doesn't stay modified.

gname = 'Sue'
def doIt(name = gname):
This is a FAQ, cf:
http://www.python.org/doc/faq/genera...etween-objects

Briefly : default args are eval'd only once at load/import time.

Any ideas how I can make the 'Lisa' assignment permanent forever in 2nd
doIt? Thanks
def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name
(Note. Contrived example substitutes for a web-type app, where, if the
page is called without arguments then it displays the global defaults.
If the page is called with form arguments then it should be able to
change the global defaults)
Modifying globals from within a function is usually a very bad idea.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 6 '06 #2

P: n/a

Bruno Desthuilliers wrote:
def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name
Thanks Bruno, works a treat...

Jul 6 '06 #3

P: n/a
meridian wrote:
Bruno Desthuilliers wrote:
>>def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name


Thanks Bruno, works a treat...
But still very probably a bad idea.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 6 '06 #4

P: n/a

Bruno Desthuilliers wrote:
meridian wrote:
Bruno Desthuilliers wrote:
>def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name

Thanks Bruno, works a treat...
But still very probably a bad idea.
Ok, my curiosity is pique'd - is there a better way to hold my
app/module globals?
I must say I'd prefer not to write global <varin every function, for
every global var I need.
Maybe there's a simpler way to structure?... by a global class or
something?
Cheers
Steve

Jul 6 '06 #5

P: n/a

You mentioned earlier that
"Modifying globals from within a function is usually a very bad idea."

Most of my app consists of functions or class/object functions, that's
all I do in OOP.
Did you mean that modifying globals from anywhere is bad? or globals
are bad? or don't code using methods/functions? not sure...

Jul 6 '06 #6

P: n/a
meridian a écrit :
Bruno Desthuilliers wrote:
>>meridian wrote:
>>>Bruno Desthuilliers wrote:
def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name

Thanks Bruno, works a treat...

But still very probably a bad idea.

Ok, my curiosity is pique'd - is there a better way to hold my
app/module globals?
Probably !-)

Now which one depends on your app design and execution model...
I must say I'd prefer not to write global <varin every function, for
every global var I need.
Maybe there's a simpler way to structure?... by a global class or
something?
<ot>What is a "global class" ?</ot>

The problem with "app globals" is that they introduce too much coupling
(you end up having all your code depending on the globals). So the first
thing to do is identify who really needs to know what, and who is
responsible for knowing what. Anyway, most globals should be
configuration stuff - so usually read only. There are very good reasons
to avoid modifying globals in functions, and specially when it comes to
web programming where you have to handle concurrent access (which is why
I insist on telling you that what you want to do may be very dangerous).

Usually one uses a variant of the MVC, which helps separating concerns :
the model is about data (structure and persistance), the view(s) about
outputs (display data), and the controler about inputs (processing the
request). The flow is something like: controller parses request, takes
any appropriate action, selects appropriate elements from the model,
feed'em to appropriate view, and returns the result of view execution as
a response (general scheme, depends on whether it's plain cgi,
mod_python, fastcgi, wsgi, standalone server or whatnot).

It's clear that the controler needs some knowldge about the model and
the views, that the views are tightly coupled to the model but don't
need to know about the controller, and that the model just don't give a
damn about both controller and views. So we have:

controller -depends on model and view
view -depends on model
model -depends on nobody

Since handling a request is the controller's duty, the model should not
know about the request. The only 'global' things the model has to know
are related to data access configuration (db connection string, physical
path to resources on the filesystem etc...). Since the model is called
by the controller, it's the controller's job to pass these informations
to the model when appropriate.

Views may also need to access app-wide settings like urls to resources,
localisation stuff etc. Here again, since views are invoked by the
controller, it's usually the controller that is responsible for passing
relevant knowledge to the views - either directly (raw data) or
indirectly (thru some helper objects that holds the required knowledge
and are called by the view code).

As you can see, you've already eliminated any needs for globals in both
the views and the model (view or model specific module-level
pseudo-constants set aside, but then it's mostly safe).

I don't know which web solution you use, but I strongly suggest that you
take some time studying existing web applications or frameworks like
Trac, Django, CherryPy etc.

HTH
Jul 6 '06 #7

P: n/a
meridian a écrit :
You mentioned earlier that
"Modifying globals from within a function is usually a very bad idea."

Most of my app consists of functions or class/object functions, that's
all I do in OOP.
Did you mean that modifying globals from anywhere is bad?
Yes, definitively. Even without concurrent access, it very rapidly turns
the code into an unscrutable mess.
or globals
are bad?
Mostly, yes.

As usual, this is not a hard rule but a guideline. But I use as few
globals as possible, and almost all of them are read-only. The very few
exceptions are dirty hacks, mostly called at init time.
or don't code using methods/functions?
Err...
Jul 6 '06 #8

P: n/a
Thanks Bruno. Not only do you give solutions to my problem but also
throw in great MVC tutorials too.
You're a gent.

I'm using
controller -A CherryPy app
views -Cheetah Templating for the html & data
model -mostly SQLite DB using pysqlite
also Config

It's only a desk-web app for single-user, so no concurrency issues.
However, taking on board your advice to avoid globals, I've now
realised that the info that I need to retain between pages can simply
be session information (for the only user) that can be initialised at
startup from the config.
So I'm looking at just storing it all in the cherrypy.session ram vs
using python globals.
Thanks again & Regards
Steve

Jul 7 '06 #9

P: n/a
meridian wrote:
Thanks Bruno. Not only do you give solutions to my problem but also
throw in great MVC tutorials too.
You're a gent.
(blush)
I'm using
controller -A CherryPy app
views -Cheetah Templating for the html & data
model -mostly SQLite DB using pysqlite
also Config

It's only a desk-web app for single-user, so no concurrency issues.
Err... I would not be so confident wrt/ this point. What about having
two browser windows opened on different pages of the app ?
However, taking on board your advice to avoid globals, I've now
realised that the info that I need to retain between pages can simply
be session information (for the only user) that can be initialised at
startup from the config.
So I'm looking at just storing it all in the cherrypy.session ram vs
using python globals.
Think this will be better !-)

But still, avoid overusing sessions - ie, don't make session available
to objects just for covenience when you can pass required data as params.

My 2 cents...

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 7 '06 #10

P: n/a

Bruno Desthuilliers wrote:
>
def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name
Sorry for this very basic question, but I don't understand why I should
add the global into the function body before using it.
This function works even if I don't add the global.
Just to try this out, I wrote this variant:

gname = 'Luis'

def doIt2(name=None):
if name is None:
name = gname
return name

print doIt2() --returns Luis.

So, what's the point of writing the function this way instead?

def doIt2(name=None):
global gname
if name is None:
name = gname
return name
luis

Jul 7 '06 #11

P: n/a
try this:

gname = 'nate'
def test():
gname = 'amy'
print gname

test()
print gname

outputs:
'amy'
'nate'

whereas this:
gname = 'nate'
def test():
global gname
gname = 'amy'
print gname

test()
print gname

outputs:
'amy'
'amy'

Luis M. González wrote:
Bruno Desthuilliers wrote:

def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name

Sorry for this very basic question, but I don't understand why I should
add the global into the function body before using it.
This function works even if I don't add the global.
Just to try this out, I wrote this variant:

gname = 'Luis'

def doIt2(name=None):
if name is None:
name = gname
return name

print doIt2() --returns Luis.

So, what's the point of writing the function this way instead?

def doIt2(name=None):
global gname
if name is None:
name = gname
return name
luis
Jul 7 '06 #12

P: n/a

nate wrote:
try this:

gname = 'nate'
def test():
gname = 'amy'
print gname

test()
print gname

outputs:
'amy'
'nate'

whereas this:
gname = 'nate'
def test():
global gname
gname = 'amy'
print gname

test()
print gname

outputs:
'amy'
'amy'
OK, so I should include the global only if I plan to modify it.
Otherwise, I don't need to include it. Am I right?

Jul 7 '06 #13

P: n/a
OK, so I should include the global only if I plan to modify it.
Otherwise, I don't need to include it. Am I right?
I guess you could say that's true. I'm hardly an expert so I couldn't
say there aren't other potential ramifications. (anyone?)

But, as a rule I would declare the global variable always because
1) it makes my intention clear
2) if I later decided to modify the global variable, I would be less
likely to introduce a bug by forgetting to declare it global.

Jul 8 '06 #14

P: n/a
On Fri, 07 Jul 2006 19:41:36 -0400, Luis M. González <lu*****@gmail.com>
wrote:
..
..
OK, so I should include the global only if I plan to modify it.
Otherwise, I don't need to include it. Am I right?
Correct. Globals are always available to read from. You need to declare
them if you want to modify them in another scope. Like nate, I also tend
to declare them all the time if I am going to use them, just for clarity.

M.
Jul 8 '06 #15

P: n/a

Markus Wankus wrote:
On Fri, 07 Jul 2006 19:41:36 -0400, Luis M. González <lu*****@gmail.com>
wrote:
.
.
OK, so I should include the global only if I plan to modify it.
Otherwise, I don't need to include it. Am I right?

Correct. Globals are always available to read from. You need to declare
them if you want to modify them in another scope. Like nate, I also tend
to declare them all the time if I am going to use them, just for clarity.

M.
Thank you guys!
Luis

Jul 8 '06 #16

P: n/a
Luis M. González a écrit :
Bruno Desthuilliers wrote:
>>def doIt(name=None):
global gname
if name is None:
name = gname
else:
gname = name


Sorry for this very basic question, but I don't understand why I should
add the global into the function body before using it.
You have to do it if you intend to rebind the name in the function's
body (else this would create the name in the local namespace).
This function works even if I don't add the global.
Just to try this out, I wrote this variant:

gname = 'Luis'

def doIt2(name=None):
if name is None:
name = gname
return name

Please read more carefully the OP's code:
"""
gname = 'Sue'
def doIt(name = gname):
global gname
gname = name
print 'doIt name', name, 'gname', gname
"""

As you can see, it rebinds gname.
print doIt2() --returns Luis.

So, what's the point of writing the function this way instead?

def doIt2(name=None):
global gname
if name is None:
name = gname
return name
In this case, you don't need the global statement (but keeping it makes
clear you're using a global name, which is not a bad thing in itself...)

Now if it's about LOCs count, here's a shorter equivalent:
doIt3 = lambda name : (name, gname)[name is None]
Jul 9 '06 #17

P: n/a
Luis M. González a écrit :
(snip)
OK, so I should include the global only if I plan to modify it.
Otherwise, I don't need to include it. Am I right?
s/modify/rebind/
Jul 9 '06 #18

This discussion thread is closed

Replies have been disabled for this discussion.