#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Posts
    4
    Rep Power
    0

    Imported module scope, procedures, namespaces


    I'm trying to understand scope and procedures.

    http://docs.python.org/2/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

    Gives this clear description:
    In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the functionís body, itís assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as Ďglobalí.
    And this jives with each of the 4 procs below, except proc1. Can anybody explain why I'm able to change arcpy.env.workspace inside my procedure (and have it stick outside) but I can't change len inside my proc and have it stick outside? Is it because arcpy.env.workspace is in a different namespace; whereas, the built-in functions are not?

    Thanks for your help.

    Code:
    import arcpy
    
    arcpy.env.workspace ='C:/Temp'
    
    def proc1():
    	arcpy.env.workspace = 'C:/other'
    
    proc1()
    
    print arcpy.env.workspace
    #prints C:/other
    
    w = 'a'
    def proc2():
    	w = 5
    
    proc2()
    print w
    #prints a
    def proc3():
    	print w+'b'
    
    proc3()
    #prints ab
    
    def proc4():
    	len = 1
    proc4()
    print len('abc')
    #prints 3
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,837
    Rep Power
    480
    Maybe that answer in the FAQ isn't as clear as it could be. The case you show isn't covered. If you examine your globals you'll see that arcpy is a key, but arcpy.env is not.

    >>> 'arcpy' in globals()
    True

    Simple example using an object instead of another module:
    Code:
    >>> class c: pass
    ... 
    >>> o = c()
    >>> def f(): o.new_variable = 'hi world'
    ... 
    >>> vars(o)
    {}
    >>> f()
    >>> vars(o)
    {'new_variable': 'hi world'}
    >>>
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    114
    Rep Power
    3
    Well, let's go back to that quote you posted (bold mine):
    In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the functionís body, itís assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as Ďglobalí.
    arcpy.env.workspace is not a variable, it is an attribute.
  6. #4
  7. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,837
    Rep Power
    480
    So whether an object is called an attribute or a variable depends on the frame of reference?

    If module.py contains
    Code:
    # module.py
    # variable is certainly a global variable in module
    variable = 'a global variable'
    And then I have also
    Code:
    #main.py
    
    import module
    
    def f():
        module.variable = 'a module attribute????'
    [code]Code tags[/code] are essential for python code and Makefiles!
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Posts
    4
    Rep Power
    0
    Hi,

    thanks for the responses! I guess what I'm looking for is a set of general rules about this.

    Let me give it a stab. So far, we have:

    1. If it's a global variable in my script, I can access it within a procedure, but not change its value. I can read it, but if I write a value it is considered to be a local to the procedure variable.

    2. If it's a class property variable (or attribute), I can read and write it's value.


    So, in summary, the FAQ I quoted only applies to module local/global variables OR built-in functions?

    In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the functionís body, itís assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as Ďglobalí.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    114
    Rep Power
    3
    Originally Posted by b49P23TIvg
    So whether an object is called an attribute or a variable depends on the frame of reference?

    If module.py contains
    Code:
    # module.py
    # variable is certainly a global variable in module
    variable = 'a global variable'
    And then I have also
    Code:
    #main.py
    
    import module
    
    def f():
        module.variable = 'a module attribute????'
    Variables and attributes are better seen as kinds of names rather than kinds of objects. "Attributes" are just syntactic sugar for getattr() and setattr(). The implementation of getattr(a_module, "some_name") on searches the module's global scope for an object named some_name and returns it.

    Originally Posted by gis
    1. If it's a global variable in my script, I can access it within a procedure, but not change its value. I can read it, but if I write a value it is considered to be a local to the procedure variable.
    You can write to a global, you just have to tell Python you're doing so.
    Code:
    >>> x = 5
    >>> def f():
    ... 	global x
    ... 	x = 6
    ... 
    >>> f()
    >>> x
    6
    2. If it's a class property variable (or attribute), I can read and write it's value.
    Only if the class allows you to. All attributes are read/write by default, but classes can create read-only or write-only attributes if they want to, using magic methods and descriptors.
    Last edited by Nyktos; March 20th, 2013 at 08:48 PM.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2009
    Posts
    474
    Rep Power
    33
    You use id() to see/check if variables point to the same memory which will verify or disprove an assumption.
    Code:
    def test_id(w=None):
        if not w:
            w=0
        print w, id(w)
    
    w=1
    print w, id(w)
    test_id()
    w += 1
    test_id(w)
    print w, id(w) 
    
    """ prints
    1 28137400
    0 28137424
    2 28137376
    2 28137376
    """
    Last edited by dwblas; March 20th, 2013 at 05:29 PM.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Posts
    4
    Rep Power
    0
    Thanks for the feedback. So the modified rules are:


    1. If it's a global variable in my script, I can access it within a procedure, but not change its value (unless I insert a global statement for that var within my procedure). I can read it, but if I write a value it is considered to be a local to the procedure variable.

    2. If it's an imported module property or a class read/write attribute, I can read and write it's value within a procedure and the change will persist outside the procedure.

    BUT it seems like I need to modify these rules further to account for mutable data types?

    Code:
    >>> def augment( mylist, myint ):
    ... mylist.append("some value")
    ... myint = myint + 1
    ...
    >>> alist = ["first entry"]
    >>> num = 5
    >>> print alist
    ['first entry']
    >>> print num
    5
    >>> augment(alist, num)
    >>> print alist
    ['first entry', 'some value']
    >>> print num
    5
  16. #9
  17. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,837
    Rep Power
    480
    There's got to be a way to simplify your death by definition. If you access the name with a dot then you can change it. If it's mutable.
    [code]Code tags[/code] are essential for python code and Makefiles!
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    114
    Rep Power
    3
    You can call an object's methods from any scope that can "see" the object, and a method will do the same thing no matter where it was called from. If the method is one that mutates the object, that's another way that functions can mess around with things in other scopes, yes.

IMN logo majestic logo threadwatch logo seochat tools logo