Scope and program structure problems

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Tue Jul 1 17:18:16 CEST 2008


John Dann a écrit :
> Many thanks for the repsonse - much appreciated. 
> 
> And sorry - yes I was probably compounding two separate issues here -
> the GUI one and the variable scope one. Maybe the wxPython list would
> be the best place to ask more about the GUI side of things.
> 
> Then actually I can simplify my remaining question quite a lot - I
> know you've partly answered this already but let me just rephrase
> this:
> 
> It must be commonplace to first use a variable or object

What difference do you make between a variable and an object in this 
context ?

> within one
> function in a module and then want to use it again  - perhaps still
> with the same value

For which definition of "same value" ? Remember, Python has *no* 
primitive types. Everything is an object.

> as in the first function - in a second function.
> So what's the recommended Python way round this?

This is way too general to give a single straight answer - whatever the 
language FWIW. Are both function in the same module ? Are they methods 
of a same object ? Is the first function calling the second or are they 
totally unrelated ?

> If I was using .Net
> then I'd be declaring the variables/objects explicitly

I personnally find the assignment, import, class and def statements (all 
having a binding behaviour) to be rather explicit.

> and could set
> their scope according to how/where they were declared.

Names bound at the top-level are globals to the module. Names bound 
within a function (including arguments) are locals, unless there has 
been a global statement for them before in the same function's body. 
Names bound within a class statement lives in the class's namespace (IOW 
: they become class attributes, shared by all instances). And names 
bound as object attributes (using either obj.name = whatever or 
setattr(obj, "name", whatever)) become, well, object attributes.

Now there may be a couple points worth paying attention to :

1/ some types (numerics, strings and tuples at least) are immutable. 
When doing :

   i = 1
   i = 2

the second assignment doesnt mutate the integer object bound to i, but 
rebinds i to another integer object.

2/ the scope of a name isn't necessarily related to the scope of the 
object bound to that name.

As an example, function's parameters *names* are local to the function, 
but the actual arguments - the objects passed when calling the function 
- are not.

IOW, rebinding a parameter name withing a function body will rebind the 
name locally, but will not affect the object originally bound to that 
name. But *mutating* an object passed as argument *will* (off course) 
affect the object outside the function.


> But if the
> Python way is not to declare vars before use

For which definition of "var" and "use" ? Did you really try to use a 
name that didn't exist in the accessible namespace - I mean, "use" for 
anything else than binding ?

The first binding of a name in a namespace *is* the 'declaration'. If a 
name is not defined in the currently accessible namespace, and you try 
to do anything else than binding it, you'll get an exception.

> then this must create
> some problems for cross-function use.

If what you mean is that it makes it harder to litter you code with true 
global variables, then it's obviously a *very* good thing IMHO !-)

But no, there's no more problem with shared state in Python than in any 
other (imperative) language I know - usually less in fact since there's 
no "application global" namespace. Most of the time, the appropriate way 
to share state is to use classes - heck, that's what they were created 
for, isn't it ?-). Sharing state thru module-level variables is ok as 
long you only access it for reading (pseudo-constants etc).

Sometimes, it's ok to use a module-level variable read-write, but this 
should be restricted to this particular module's  implementation stuff 
(IOW : the name is not part of the API, and only functions / methods in 
this same module access it), and never done without a clear enough 
understanding of Python's namespaces and bindings.


> So it is best to declare such vars at the module level (ie outside of
> a function) and set eg to Null/None or to assign them with a keyword
> such as global or static (assuming that concept applies in Python)

it doesnt.

> at first use inside a function or what?

Usually, when you really need a module-level variable to be shared 
read-write between functions, it happens that you can bind it to a 
sensible default. Now what is a "sensible default" depends on the 
concrete use case. Anyway, by all means, explicitely bind this name at 
the top-level, before any code accessing it, and if possible with a 
comment about this name being shared read/write by functions x and y.

My 2 cents...




More information about the Python-list mailing list