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

Turn of globals in a function?

P: n/a

Is there a way to hide global names from a function or class?

I want to be sure that a function doesn't use any global variables by
mistake. So hiding them would force a name error in the case that I
omit an initialization step. This might be a good way to quickly
catch some hard to find, but easy to fix, errors in large code blocks.

Examples:

def a(x):
# ...
x = y # x is assigned to global y unintentionally.
# ...
return x

def b(x):
# hide globals somehow
# ...
x = y # Cause a name error
# ...
return x
y = True
a(False): True
b(False):

*** name error here ***
Ron_Adam
Jul 18 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Ron_Adam wrote:
Is there a way to hide global names from a function or class?

I want to be sure that a function doesn't use any global variables by
mistake. So hiding them would force a name error in the case that I
omit an initialization step. This might be a good way to quickly
catch some hard to find, but easy to fix, errors in large code blocks.

Examples:

def a(x):
# ...
x = y # x is assigned to global y unintentionally.
# ...
return x

def b(x):
# hide globals somehow
# ...
x = y # Cause a name error
# ...
return x
y = True

a(False):
True

b(False):
*** name error here ***
Ron_Adam

For testing, you could simply execute the function in an empty dict:
a = "I'm a"
def test(): ... print a
... test() I'm a exec test.func_code in {} Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 2, in test
NameError: global name 'a' is not defined
This would get more complicated when you wanted to test calling with parameters,
so with a little more effort, you can create a new function where the globals
binding is to an empty dict:
from types import FunctionType as function
testtest = function(test.func_code, {})
testtest() Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 2, in test
NameError: global name 'a' is not defined


HTH

Michael

Jul 18 '05 #2

P: n/a
On Sat, 26 Mar 2005 20:01:28 GMT, Ron_Adam <ra****@tampabay.rr.com> wrote:

Is there a way to hide global names from a function or class?

I want to be sure that a function doesn't use any global variables by
mistake. So hiding them would force a name error in the case that I
omit an initialization step. This might be a good way to quickly
catch some hard to find, but easy to fix, errors in large code blocks.

Examples:

def a(x):
# ...
x = y # x is assigned to global y unintentionally.
# ...
return x

def b(x):
# hide globals somehow
# ...
x = y # Cause a name error
# ...
return x

If you put the above def b in e.g. a_module.py,
and do a (untested ;-)

from a_module import b

instead of defining it locally, then the global references
from b (and whatever else you import from a_module)
should be to the global dict defined for a_module (i.e., its
outermost scope), not to the globals where you do the import.
y = True
a(False):True Should work if you define a in place having same scope as the y assignmentb(False):

*** name error here ***

UIAM it should do this if you import b as above.

Regards,
Bengt Richter
Jul 18 '05 #3

P: n/a
On Sat, 26 Mar 2005 12:18:39 -0800, Michael Spencer
<ma**@telcopartners.com> wrote:
Ron_Adam wrote:
Is there a way to hide global names from a function or class?

I want to be sure that a function doesn't use any global variables by
mistake. So hiding them would force a name error in the case that I
omit an initialization step. This might be a good way to quickly
catch some hard to find, but easy to fix, errors in large code blocks.

Examples:

def a(x):
# ...
x = y # x is assigned to global y unintentionally.
# ...
return x

def b(x):
# hide globals somehow
# ...
x = y # Cause a name error
# ...
return x
y = True

>a(False):
True

>b(False):


*** name error here ***
Ron_Adam

For testing, you could simply execute the function in an empty dict:
>>> a = "I'm a"
>>> def test(): ... print a
... >>> test() I'm a >>> exec test.func_code in {} Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 2, in test
NameError: global name 'a' is not defined >>>

I didn't know you could do that. Interesting. :)

I was hoping for something in line that could use with an assert
statement. But this is good too, I'll have to play around with it a
bit. Thanks.

Ron

This would get more complicated when you wanted to test calling with parameters,
so with a little more effort, you can create a new function where the globals
binding is to an empty dict:
>>> from types import FunctionType as function
>>> testtest = function(test.func_code, {})
>>> testtest() Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 2, in test
NameError: global name 'a' is not defined >>>


HTH

Michael

Jul 18 '05 #4

P: n/a
If you put the above def b in e.g. a_module.py,
and do a (untested ;-)

from a_module import b

instead of defining it locally, then the global references
from b (and whatever else you import from a_module)
should be to the global dict defined for a_module (i.e., its
outermost scope), not to the globals where you do the import.
y = True
>a(False):

True

Should work if you define a in place having same scope as the y assignment
>b(False):

*** name error here ***

UIAM it should do this if you import b as above.

Regards,
Bengt Richter


Good suggestion. Thanks. I was somewhat aware of the modular scope,
but was looking for way to apply it on a more local level. Michael's
suggestion looks interesting for that.

Ron_Adam

Jul 18 '05 #5

P: n/a
Ron_Adam <ra****@tampabay.rr.com> wrote in message news:<6q********************************@4ax.com>. ..
Is there a way to hide global names from a function or class?

I want to be sure that a function doesn't use any global variables by
mistake. So hiding them would force a name error in the case that I
omit an initialization step. This might be a good way to quickly
catch some hard to find, but easy to fix, errors in large code blocks.


def noglobals(f):
.. import new
.. return new.function(
.. f.func_code,
.. {'__builtins__':__builtins__},
.. f.func_name,
.. f.func_defaults,
.. f.func_closure
.. )

You can use it with the Python 2.4 @decorator syntax:

@noglobals
def a(...):
.. # code here

Doing this for a class is a little more work. You will need dig inside
to perform this treatment on each method separately and handle new and
old-style classes a bit differently.

Note that this kind of function may declare globals. They will be
persistent but private to the function.

Oren
Jul 18 '05 #6

P: n/a
On 26 Mar 2005 22:51:14 -0800, or**@REMOVETHIS1.hishome.net (Oren
Tirosh) wrote:
Ron_Adam <ra****@tampabay.rr.com> wrote in message news:<6q********************************@4ax.com>. ..
Is there a way to hide global names from a function or class?

I want to be sure that a function doesn't use any global variables by
mistake. So hiding them would force a name error in the case that I
omit an initialization step. This might be a good way to quickly
catch some hard to find, but easy to fix, errors in large code blocks.


def noglobals(f):
. import new
. return new.function(
. f.func_code,
. {'__builtins__':__builtins__},
. f.func_name,
. f.func_defaults,
. f.func_closure
. )

You can use it with the Python 2.4 @decorator syntax:

@noglobals
def a(...):
. # code here


Cool! I haven't played with decorators yet. :)

I noticed the 'new' module is depreciated. It referred me to call the
object type directly instead. So this is probably the better way.

def noglobals(f):
return type(f)(
f.func_code,
{'__builtins__':__builtins__},
f.func_name,
f.func_defaults,
f.func_closure )

@noglobals
def a():
global x
try: x
except: x=0
x += 1
return x

x = 5
for n in range(10):
print a()
print x # x is still 5
So this is another, but longer, way to do a generator.

print type(a).__doc__ function(code, globals[, name[, argdefs[, closure]]])

Create a function object from a code object and a dictionary.
The optional name string overrides the name from the code object.
The optional argdefs tuple specifies the default argument values.
The optional closure tuple supplies the bindings for free variables.


What are 'free variables'?

And is there a way to directly read what names in a function are set
with the global statement? (Other than looking at the monitor. ;)

Ron_Adam

Jul 18 '05 #7

P: n/a
Oren Tirosh wrote:
def noglobals(f):
. import new
. return new.function(
. f.func_code,
. {'__builtins__':__builtins__},
. f.func_name,
. f.func_defaults,
. f.func_closure
. )


Be aware that this will render the function incapable
of seeing *any* globals at all, including other
functions and classes defined in the same module --
which you may find rather inconvenient!

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg
Jul 18 '05 #8

P: n/a
On Thu, 31 Mar 2005 16:28:15 +1200, Greg Ewing
<gr**@cosc.canterbury.ac.nz> wrote:
Oren Tirosh wrote:
def noglobals(f):
. import new
. return new.function(
. f.func_code,
. {'__builtins__':__builtins__},
. f.func_name,
. f.func_defaults,
. f.func_closure
. )


Be aware that this will render the function incapable
of seeing *any* globals at all, including other
functions and classes defined in the same module --
which you may find rather inconvenient!

Developing this idea further...

This allows a programmer to specify what globals to allow read and or
writes.
Cheers,
Ron
#---start---
# useglobals.py

"""
A function to specify what globals and builtins
a function may access.
Author: Ronald Adam
"""

def useglobals(rw_globals=None, r_globals=None, builtins=True):
#import dis
import sys
write_list = []
read_list = []
if rw_globals != None:
rw_globals = rw_globals.replace(' ','')
write_list = rw_globals.split(',')
if r_globals != None:
r_globals = r_globals.replace(' ','')
read_list = r_globals.split(',')
if builtins == True:
read_list.extend(dir(__builtins__))
elif builtins != None:
builtins = builtins.replace(' ','')
read_list.extend(builtins.split(','))
# Add own name to read list.
read_list.append(sys._getframe(0).f_code.co_name)
read_list.extend(write_list)
#print read_list, write_list
names = sys._getframe(1).f_code.co_names
code = sys._getframe(1).f_code.co_code
#print dis.disassemble(sys._getframe(1).f_code)
i = 0
while i < len(code):
#print ord(code[i])
op = ord(code[i])
if op == 116: # dis.opmap['LOAD_GLOBAL']
oparg = ord(code[i+1]) + ord(code[i+2]) * 256
if str(names[oparg]) not in read_list:
raise NameError, "read from global name %s, detected"
% names[oparg]
elif op == 97: # dis.opmap['STORE_GLOBAL']
oparg = ord(code[i+1]) + ord(code[i+2]) * 256
if names[oparg] not in write_list:
raise NameError, "write to global name %s, detected" %
names[oparg]
if op >= 90: # dis.HAVE_ARGUMENT
i += 3 # Not sure if this is always the same?
else:
i += 1
if __name__ == '__main__':
"""
Test useglobals() function. Change values to test
for error catching.
"""

def a():
useglobals(rw_globals='x', r_globals='y,b')
# This function can read or write 'x',
# Can read 'y', and function 'b',
# and can access all builtins.
global x
y = 5
x += y
x = b(x)
return x

def b(g):
useglobals('','y,c','int')
# This function can only read 'y' and
# function 'c' in globals, and can
# only access 'int' in builtins.
g = g+y
c(int(g))
return g

def c(w):
useglobals(builtins=None)
# This function has no builtins or globals.
w = w**2
return w

y = 4
x = 5
z = 6
print a(),x,y,z

#---end---

Jul 18 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.