- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
作用域嵌套与闭包 • 嵌套定义的函数可以将内部名称绑定到外部函数的作用域中,这个绑定在外部 函数运行结束后仍然是生效的,这种技术也被称为闭包:新定义的函数中包含 了外部函数作用域的一部分 def add_func(a): def _add(b): return a + b return _add
a = add_func(1) a(1) # 2 a(2) # 3
作用域嵌套与闭包 • 可以利用默认参数绑定的规则(在定义时进行绑定)来改变作用域,从而保存 当前的值: def multipliers(n): funcs = [] for i in range(0,n): def _func(b, i = i): # 默认参数保存了当前的i的值, # 同时改变i的作用域 return i * b funcs.append(_func) return funcs ms = multipliers(10) ms[2](3) # 6, 2 * 3
a = myfunc(param1,
param2, param3) • 实际的一行可以用分号分成多个短的逻辑行(通常不推荐) a = 2; func(a)
绑定(Python)vs 赋值(C)
Python绑定指向同一个对象,可以 看作别名;没有类型限制
a = [1] b = a a[0] = 2 b[0] # 2
• 名称绑定:将等号右侧的值绑定到左侧的名称符号
绑定一个值:a = 1 绑定表达式运算的结果:a = 1 + 2 - 3 同时绑定多个:a = b = c = 1 解构绑定:(a,b) = (1,2)或a,b = (1,2)或[a,b] = (1,2) 运算的同时重新绑定:a += 1
Python的基本语法:行与行的扩展
作用域嵌套 • 定义函数是单纯的名称绑定,因此在函数内部也可以定义新的函数 • 新定义的函数有自己的作用域,同时也继承外层函数的作用域 • 如果某个名称在最内层作用域中没有被绑定,则会依次寻找外层作用域,如果 外层作用域中被绑定,则绑定到外层作用域,否则再寻找更外层作用域 • 作用域嵌套只与定义时的嵌套关系有关,与调用无关;名称不会解析到调用时 的作用域中 def func1(a,b): def func2(): return a+b return func2
复合语句 • Βιβλιοθήκη 个语句组成的具有特殊功能的结构,称为复合语句
if ... elif ... else ... while ... else ... for ... else ... with ... def ... class ... try ... except ... else ... finally ...
函数内部绑定的名称,作用域局限于函数范围;它与外部的相同名称可以具有不同的值,互不影 响;函数的参数也看作函数内部绑定的名称。相同函数每次调用的作用域也是互相独立的。 a = 1 def func(): a = 2 return a b = func() # 2 a # 1 在绑定之前就使用了相应名称的变量会报错 def func(): b = a a = 1
• 函数有额外的名称:参数
参数名称对应的值,在调用时,由调用者进行绑定
• 函数可以有返回值,返回值是调用函数的表达式的值
用return语句返回值 没有执行return语句就返回了,或者return后面没有跟表达式的情况下,返回值是None
def add(a,b): return a + b
函数与生成器函数 • • • • • 生成器函数是一种特殊的函数: 使用yield返回多个值 return只能跟空表达式(Python 2) / return可以返回一个值(Python 3) 调用生成器函数时,返回一个生成器,实际语句在生成器中执行 详细内容在后面继续
作用域嵌套与闭包 • 注意按照解析规则,解析在函数实际运行时才进行,因此闭包中包含的外部函 数作用域中的名称,对应的值随外部函数作用域中该名称绑定的值而变化 def func(): a = 1 def func2(): return a a = 2 return func2
func()()
# 2
作用域嵌套与闭包 • 警惕下面的例子: def multipliers(n): funcs = [] for i in range(0,n): def _func(b): return i * b funcs.append(_func) return funcs ms = multipliers(10) ms[2](3) # 27, 9 * 3,因为在循环结束之后,i的值是9
Python是一种纯粹的语言
知乎ID:灵剑
Python的基本语法:表达式运算与名称绑定 • 名称与绑定:相当于其他语言中的变量与赋值,但略有区别 • 所有以字母、下划线开头,由字母、下划线、数字组成的非保留字的完整单词 都是一个名称 abc _abc abc123 …… • 表达式:常量、名称和运算的组合,可以计算出一个值
可变参数的相反操作:解构绑定参数 调用时可以使用元组和字典提供参数 def func(a,b): ... c = (1,2) func(*c) # 等效于:func(1,2) d = {'a': 1, 'b': 2} func(**d) # 等效于:func(a = 1, b = 2)
绑定、解析与作用域
C赋值复制了原始的值,复制之后两 个值不再关联;有类型限制
struct my_type a = {}, b; a.b = 1; b = a; a.b = 2; b.b; // 1
重新绑定与解除绑定 已经绑定的符号可以重新绑定到新的值,绑定之后与原来的值的关系解除: a = [1,2] b = a a = [2,3] b # [1,2] a[0] = 3 b[0] # 1 可以用del语句强制解除某个绑定: a = [1,2] del a
特殊绑定 • 三种语法可以不使用 = 进行绑定 • import:
• import some_module:导入模块some_module,绑定到some_module
• from some_module import a,b:导入模块some_module,将some_module.a, some_module.b分别绑定到a,b
可变参数 • 可变参数是特殊的参数绑定方式 def var_func(a, b, *more_args, **more_kw_args): ... var_func(1,2,3,4, test = 5) # a = 1, b = 2, more_args = (3,4), # more_kwargs = {'test': 5} • 如果定义了*args形式的参数,调用时,所有没有匹配到其他参数的多余的位置 参数,构成元组,绑定到args • 如果定义了**kwargs形式的参数,调用时,所有没有匹配到其他参数的多余的 命名参数,构成字典,绑定到kwargs
# 1 # 报错
嵌套调用与递归 • 函数内调用其他函数的过程,是首先将要调用的函数名称解析到对应的函数对 象,然后执行函数对象,解析函数名称这一步也是在运行时进行的 • 因此,函数内部可以调用尚未定义的函数,包括自己 def a(n): return b(n-1) if n else 0 def b(n): return a(n-1) if n else 1 def c(n): return c(n-1) + c(n-2) if n > 2 else 1
# 报错
绑定、解析与作用域 • 由于相同名称在不同作用域中可以有不同的值,从名称获取值的过程称为解析 • 函数内部名称的解析服从以下规则:
如果这一名称在函数内的任意语句中被绑定(包括普通绑定、特殊绑定以及参数绑定),则该 名称解析的作用域是当前作用域 否则,该名称将被解析到外部作用域
a = 1 def func(): print a def func2(): print a a = 2
• Python的简单语句,通常是一个绑定语句,或者一个表达式,行尾不需要分号之类的 分隔符 • Python中,逻辑的行可以与实际的行不同:
• Python的每行代码对应一个逻辑行 • 行太长时,可以由多个实际的行可以组成一个逻辑行: • 使用\转义换行符:
a = 1 + 2 + \
3 + 4 • 当Python识别出表达式未完(如括号不匹配)时,会自动扩展下一行
函数定义 def func(a,b): ... return ... func(1,2) func(var1, var2) return_value = func(3,4)
函数定义 • 函数定义将新定义的函数对象绑定到选定的名称上 • 函数是一种复合语句:
函数内部的语句在调用时执行,每次调用执行一次
global作用域 • 最外层的作用域称为全局作用域(global) • 全局作用域其实包含两层:
• import some_module as m:导入模块some_module,绑定到m • from some_module import a as a1, b as b2 :导入模块some_module,将 some_module.a绑定到a1,some_module.b绑定到a2
• 函数定义:
Python的基本语法:表达式运算与名称绑定 • 表达式:值与名称运算的结果
算数表达式:(1 + 2) / 3 + 6 逻辑表达式:(a and b) or (c and d), a if b else c 调用表达式:func(p1, p2) yield表达式:yield value (与生成器有关)
def my_gen(): for i in range(0, 100): yield i * i
参数绑定 • 调用方有两种绑定参数的方式:
按顺序绑定:从左到右指定的每个参数,绑定到参数列表中从左到右对应的名称上 按名称绑定:使用 name = value的方式,直接指定要绑定的参数
• 两种方式可以混用,但不可以同时指定同一个参数 • 参数在函数内可以重新绑定到其他值,解开与调用方传入值的关系 def func(a,b): ... func(1,2) func(a = 1, b = 2) func(1, b = 2) func(1, 2, a = 3) # 出错
• def my_func(a,b): ... 定义函数,并且绑定到my_func
• 类定义:
• class my_class(object): ... 定义类,并且绑定到my_class
特殊绑定 特殊绑定除了语法以外,与普通绑定完全等价 def myfunc(a,b): ... myfunc_alias = myfunc # 可以用于绑定其他名称 myfunc_alias(1,2) myfunc = 3 # 可以重新绑定 del myfunc # 可以解除绑定
默认参数
• 定义函数时,可以指定参数的默认值,如果调用方未绑定该参数,则使用默认值
• 可以理解为:在定义函数时已经绑定了该参数的值,如果调用时重新指定则重新绑定该参数到新的 值,否则使用旧的绑定 • 服从绑定的一般规则:所有调用中默认参数绑定的是相同对象 • 默认参数的绑定在定义时进行
警惕:绑定默认值到可变类型时需要格外注意 def func(v, a = []): a.append(v) return a a = func(1) # [1] b = func(1) # [1,1] a # [1,1] • 默认值必须从后向前指定,不能在有默认值的参数后加没有默认值的参数
• 复合语句通常在行尾以冒号结束,内部包含的语句范围以缩进标示,因此不需 要表示结束的语法 • 有多个子句的复合语句,每个子句的缩进应当相同
特殊语句 • 少数简单语句既不是赋值也不是表达式
assert pass del print (Python 2) return raise break continue import global nonlocal (Python 3) exec