第十六章 Function Basics
Coding Functions
- def is executable code.:函数可嵌套
- def creates an object and assigns it to a name.:function object,function name.
- lambda creates an object but returns it as a result.
- return sends a result object back to the caller.
- yield sends a result object back to the caller, but remembers where it left off
- global declares module-level variables that are to be assigned.
- nonlocal declares enclosing function variables that are to be assigned.
- Arguments are passed by assignment (object reference).
- Arguments are passed by position, unless you say otherwise
- Arguments, return values, and variables are not declared.
def name(arg1, arg2,... argN):
...
return value
第十七章 Scopes
function’s namespace
three different scopes:
- If a variable is assigned inside a def, it is local to that function.
- If a variable is assigned in an enclosing def, it is nonlocal to nested functions.
- If a variable is assigned outside all defs, it is global to the entire file.
Comprehension variables:in 3.X, such variables are local to the expression itself in all comprehension forms: generator, list, set, and dictionary.
y, z = 1, 2 # Global variables in module
def all_global():
global x # Declare globals assigned
x = y + z # No need to declare y, z: LEGB rule
all_global()
print(x) #输出3
# thismod.py
var = 99 # Global variable == module attribute
def local():
var = 0 # Change local var
def glob1():
global var # Declare global (normal)
var += 1 # Change global var
def glob2():
var = 0 # Change local var
import thismod # Import myself
thismod.var += 1 # Change global var
def glob3():
var = 0 # Change local var
import sys # Import system table
glob = sys.modules['thismod'] # Get module object (or use __name__)
glob.var += 1 # Change global var
def test():
print(var)
local(); glob1(); glob2(); glob3()
print(var)
E layer:the local scopes of any and all enclosing function’s local scopes. 或statically nested scopes
def f1():
X = 88
def f2():
print(X) # Remembers X in enclosing def scope
return f2 # Return f2 but don't call it
action = f1() # Make, return function
action() # Call it now: prints 88
Factory Functions: Closures:
def maker(N):
def action(X): # Make and return action
return X ** N # action retains N from enclosing scope
return action
f = maker(2)
print(f,f(3),f(4))
>>> ================================ RESTART ================================
>>>
<function maker.<locals>.action at 0x000000000080CBF8> 9 16
def f1():
x = 88 # Pass x along instead of nesting
f2(x) # Forward reference OK
def f2(x):
print(x) # Flat is still often better than nested!
f1()
>>> ================================ RESTART ================================
>>>
88
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()
print(acts[0],acts[0](2),acts[1](2),acts[2](2),acts[3](2),acts[4](2),sep='\n')
<pre name="code" class="python">>>> ================================ RESTART ================================
>>>
<function makeActions.<locals>.<lambda> at 0x000000000276CBF8>
16
16
16
16
16
def makeActions():
acts = []
for i in range(5): # Use defaults instead
acts.append(lambda x, i=i: i ** x) # Remember current i
return acts
acts = makeActions()
print(acts[0],acts[0](2),acts[1](2),acts[2](2),acts[3](2),acts[4](2),sep='\n')
>>> ================================ RESTART ================================
>>>
<function makeActions.<locals>.<lambda> at 0x0000000002E6CBF8>
0
1
4
9
16
The nonlocal Statement in 3.X:
def func():
nonlocal name1, name2, ... # OK here
>>> nonlocal X
SyntaxError: nonlocal declaration not allowed at module level
- global makes scope lookup begin in the enclosing module’s scope and allows
names there to be assigned. Scope lookup continues on to the built-in scope if the
name does not exist in the module, but assignments to global names always create
or change them in the module’s scope. - nonlocal restricts scope lookup to just enclosing defs, requires that the names already
exist there, and allows them to be assigned. Scope lookup does not continue
on to the global or built-in scopes.
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
>>> F = tester(0)
>>> F('spam') # Increments state on each call
spam 0
>>> F('ham')
ham 1
>>> F('eggs')
eggs 2
>>> G = tester(42) # Make a new tester that starts at 42
>>> G('spam')
spam 42
>>> G('eggs') # My state information updated to 43
eggs 43
>>> F('bacon') # But F's is where it left off: at 3
bacon 3
First, unlike the global statement, nonlocal names really must have previously been assigned in an enenclosing
def’s scope when a nonlocal is evaluated, or else you’ll get an error
def tester(start):
def nested(label):
global state # Nonlocals must already exist in enclosing def!
state = 0
print(label, state)
return nested
SyntaxError: no binding for nonlocal 'state' found
def tester(start):
def nested(label):
global state # Globals don't have to exist yet when declared
state = 0 # This creates the name in the module now
print(label, state)
return nested
>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0
Second, nonlocal restricts the scope lookup to just enclosing defs;
State with nonlocal: 3.X only:
State with Globals: A Single Copy Only:
State with Classes: Explicit Attributes (Preview):
State with Function Attributes: 3.X and 2.X:
State with mutables: Obscure ghost of Pythons past?: