Scopes-----Learning Python

1. Scopes: the places where variables are defined and looked up. 


2. When you use a name in a program, Python creates, changes, or looks up the name in what is known as a "namespace"-a place where names live. 

the term scope refers to a namespace: the location of a name's assignment in your source code determines the scope of the name's visibility to your code.  


3. by default, all names assigned inside a function are associated with that function's namespace, and no other. 


• Names assigned inside a def can only be seen by the code within that def. You cannot even refer to such names from outside the function.


• Names assigned inside a def do not clash with variables outside the def, even if the same names are used elsewhere. A name X assigned outside a given def (i.e., in a different def or at the top level of a module file) is a completely different variable from a name X assigned inside that def.


4. 

1) The enclosing module is a global scope. each module is a global scope. 

2) the global scope span a single file only.( when you hear global in python, think 'odule)

3) assigned names are local unless declared global or nonlocal. 

4) All other names are enclosing function locals, globals, or built-ins.

5) Each call to a function creates a new local scope(Each call to a function creates a new local scope)


5. Name Resolution: The LEGB Rule


1) With def statement:


• Name assignments create or change local names by default.


• Name references search at most four scopes: local, then enclosing functions (if any), then global, then built-in.


• Names declared in global and nonlocal statements map assigned names to enclosing module and function scopes, respectively.


 When you use an unqualified name inside a function, Python searches up to four scopes—the local (L) scope, then the local scopes of any enclosing (E) defs and lambdas, then the global (G) scope, and then the built-in (B) scope—and stops atthe first place the name is found. If the name is not found during this search, Python reports an error.

NOTE: this only apply to simple variable name. for attribute name is another thing



Comprehension variables—[X for X in I] X is local to the expression itself 

Exception variables—except E as X. X is local to the except block


6. # Global scope

X = 99 # X and func assigned in module: global

def func(Y): # Y and Z assigned in function: local

# Local scope

Z = X + Y # X is a global

return Z
func(1) # func in module: result=100

Global names: X,func

( X can be referenced inside the function without being declared global)

Local names: Y,Z 

( local variables serve as temporary names that you need only while a function is running. In fact, local variables are removed from memory when the function exits. and objects they reference may be garbage-collected if not referenced elsewhere)


7. Program Design:

1)  Minimize Global Variables

Function should rely on arguments and return values instead of globals. (the temptation to make programs difficult to understand and reuse) 


state information: information that a function needs to remember for use the next time it is called.


2) Minimize cross-file changes

 the global scope of a module file becomes attribute namespace of the module object once it is imported-importers automatically have access to all of the file's global variables.


# first.py

X = 99 # This code doesn't know about second.py

# second.py

import first

print(first.X) # OK: references a name in another file

first.X = 88 # But changing it can be too subtle and implicit


Here again, the best prescription is generally to not do this—the best way to communicate across file boundaries is to call functions, passing in arguments and getting back return values.


# first.py

X = 99

def setX(new): # Accessor make external changes explit

global X # And can manage access in a single place

X = new


# second.py

import first

first.setX(88) # Call the function instead of changing directly

This requires more code and may seem like a trivial change, but it makes a huge difference in terms of readability and maintainability—when a person reading the first module by itself sees a function, that person will know that it is a point of interface and will expect the change to the X. In other words, it removes the element of surprise that is rarely a good thing in software projects. 

Although we cannot prevent cross-file changes from happening, common sense dictates that they should be minimized unless
widely accepted across the program.


8. Nested Scope Details

1) A reference (X) looks for the name X first in the current local scope (function); then in the local scopes of any lexically enclosing functions in your source code, from inner to outer; then in the current global scope (the module file); and finally in the built-in scope (the module builtins). global declarations make the search begin in the global (module file) scope instead.


2) An assignment (X = value) creates or changes the name X in the current local scope, by default. If X is declared global within the function, the assignment creates or changes the name X in the enclosing module’s scope instead. If, on the other hand, X is declared nonlocal within the function in 3.X (only), the assignment changes the name X in the closest enclosing function’s local scope.


X = 99 # Global scope name: not used

def f1():

X = 88 # Enclosing def local

def f2():

print(X) # Reference made in nested def

f2()

f1() # Prints 88: enclosing def local

3) Factory Functions: Closures

 def maker(N):
def action(X): # Make and return action
return X ** N # action retains N from enclosing scope
return action

This defines an outer function that simply generates and returns a nested function, without calling it—maker makes action, but simply returns action without running it.


The nested function remembers integer 2, the value of the variable N in maker, even though maker has returned and exited by the time we call action. 

N from the enclosing local scope is retained as state information attached to the generated action. which is why we get back its argument suqared when it's latter called


9. Loop variables may require defaults, not scopes

def makeActions():
acts = []
for i in range(5): # Tries to remember each i
acts.append(lambda x: i ** x) # But all remember same last i!
return acts


acts = makeActions()
>>> acts[0]
<function makeActions.<locals>.<lambda> at 0x0000000002A4A400>


This doesn’t quite work, though—because the enclosing scope variable is looked up when the nested functions are later

 called, they all effectively remember the same value: the value the loop variable had on the last loop iteration.


def makeActions():
acts = []
for i in range(5): # Use defaults instead,it's evaluated when it's created 
acts.append(lambda x, i=i: i ** x) # Remember current i
return acts


>>> acts = makeActions()
>>> acts[0](2) # 0 ** 2
0
>>> acts[1](2) # 1 ** 2
1
>>> acts[2](2) # 2 ** 2
4
>>> acts[4](2) # 4 ** 2


we must pass in the current value of the enclosing scope's variable with a default. 

Because defaults are evaluated when the nested function is created( not when it's latter called), each remebers its own value for i. 


10. nonlocal statement


1) unlike global nonlocal applies to a name in an enclosing function's scope, not the global module scope outside all defs.


2) unlike global, nonlocal names must already exist in the enclosing function's scope when declared.  

This provides a way for enclosing functions to provide writeable state information

remembered when the nested function is later called


def tester(start):

state = start # Each call gets its own state

def nested(label):

nonlocal state # Remembers state in enclosing scope

print(label, state)

state += 1 # Allowed to change it if nonlocal

return nested


3) Why nonlocal? State Retention Options

we need to declare variables nonlocal only if they need to be changed.(other enclosing scope name references are atuomatically retained as usual) and nonlocal names are still not visible outside the enclosing function.


11. ways to retain state information


1) State with nonlocal: 3.X only


2)  State with Globals: A Single Copy Only

def tester(start):

global state # Move it out to the module to change it

state = start # global allows changes in module scope

def nested(label):

global state

print(label, state)

state += 1

return nested


>>> F = tester(0)

>>> F('spam') # Each call increments shared global state

spam 0

>>> F('eggs')

eggs 1


3)  State with Classes: Explicit Attributes 


class tester: # Class-based alternative (see Part VI)

def __init__(self, start): # On object construction,

self.state = start # save state explicitly in new object

def nested(self, label):

print(label, self.state) # Reference state explicitly

self.state += 1 # Changes are always allowed


>>> F = tester(0) # Create instance, invoke __init__

>>> F.nested('spam') # F is passed to self

spam 0

>>> F.nested('ham')

ham 1


4) State with Function Attributes: 3.X and 2.X


def tester(start):

def nested(label):

print(label, nested.state) # nested is in enclosing scope

nested.state += 1 # Change attr, not nested itself

nested.state = start # Initial state after func defined

return nested

>>> F = tester(0)

>>> F('spam') # F is a 'nested' with state attached

spam 0

>>> F('ham')

ham 1

>>> F.state # Can access state outside functions too

2

 globals, nonlocals, classes, and function attributes all offer changeable state-retention options

Globals support only single-copy shared data; 

nonlocals can be changed in 3.X only; 

classes require a basic knowledge of OOP; and both classes and function attributes provide portable solutions that allow state to be accessed directly from outside the stateful callable object itself. As usual, the best tool for your program depends upon your program’s goals.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值