[Zope] global variables in externa Methods

Paul Winkler pw_lists@slinkp.com
Fri, 13 Dec 2002 10:06:48 -0800


On Fri, Dec 13, 2002 at 11:08:54AM +0100, Elena Schulz wrote:
> Hi Paul,
> 
> I want to pass many vars to some other functions of the same py-module than
> that connected to the external method. If possible not as explicid args as
> there are many and they dont' change while processing. Could be global
> constants, too.

You need to grok the simplifying power of dictionaries.
Approach and be enlightened. ;)

Here's one simple technique:

def foo(stuff={}):
    return bar(stuff) + baz(stuff)

def bar(stuff):
    return stuff.get('milk', 0) + stuff.get('cheese', 0) 

def baz(stuff):
    return stuff.get('bananas', 0) + stuff.get('tofu', 0) 


Then you can just call foo like this:
   
foo({'milk': 21, 'cheese': 22, 'tofu': 999, 'spam': 999999})

Notice I didn't pass in 'bananas'. I handle this
in the definition of baz by defaulting to 0 if stuff does
not have a 'bananas' key.

Python these days (since version 2 at least) gives you some nice
syntactic sugar for passing dictionaries around:

def foo(**args):
   ## args will be a dictionary constructed from all named 
   ## arguments passed to foo. 

   return bar(**args) + baz(**args)
   ## when used in a function call, the reverse happens:
   ## the items in the dictionary are passed as named
   ## arguments!


What you gain by using this syntax is the ability to call
foo like so:

foo(milk=1, cheese=22, tofu=12)

Finally, you can set defaults in a couple
of ways. 

You can just combine other named args with the special dictionary
argument syntax like so:

def foo(milk=0, eggs=0, **args):
   args['milk'] = milk
   args['eggs'] = eggs
   return bar(**args) + baz(**args)

But that would get tedious if there's really a lot of
args you want to create defaults for.
So define a separate defaults dictionary:

defaults = {'milk': 84, 'potatoes': 33}

def foo(**args):
   all_args = defaults.copy()  # do this or else you'll modify defaults!!
   all_args.update(args)  
   return bar(**all_args) + baz(**all_args)


now you can do:
foo(spam=27)

and it'll behave as if you did: 
foo(spam=27, milk=defaults['milk'], potatoes=defaults['potatoes'])

and you can add defaults just by adding to the
global defaults dictionary. Easy to maintain,
even with large numbers of defaults and
a large chain of function calls.

Remember that the **args syntax is just sugar;
you could skip that and have all your functions
take a single dictionary as their argument, as in
the first example I gave. To use the global defaults
with that, just do something like:

def foo(args={}):
    all_args = defaults.copy()
    all_args.update(args)
    return bar(all_args) + baz(all_args)

> By the way, is it possible to interrupt the processing of
> external methods without shutting down the server?

You want something else to interrupt them?
>From another thread in Zope?  No idea.
If that's even possible, I suspect it would be very hard.

-- 

Paul Winkler
http://www.slinkp.com
"Welcome to Muppet Labs, where the future is made - today!"