函数书

来源:互联网 发布:软件无线电 军用 编辑:程序博客网 时间:2024/05/01 09:56

函数

  • 函数
  • 作用域
    • 作用域法则
      • 变量名解析LEGB原则
      • 作用域实例
      • 内置作用域
    • global语句
      • 最小化全局变量
      • 最小化文件间的修改
      • 其他访问全局变量的方法
    • 作用域和嵌套函数
      • 嵌套作用域的细节
      • 嵌套作用域举例
        • 工厂函数
        • 使用默认参数来保留嵌套作用域的状态
        • 嵌套作用域和lambda
    • nonlocal语句

  • 函数也可以通过lambda表达式来创建。
  • lambda创建一个对象但将其作为结果返回。
#例子2:寻找序列的交集#在模块中编写函数意味着他可以被计算机中的任意程序来导入和重用def intersect(seq1,seq2):    res = []    for x in seq1:        if x in seq2:            res.append(x)    return ress1 = 'spam's2 = 'scam'# print(intersect(s1,s2))#为了公平起见,我们的intersect函数相当慢(执行嵌套循环),可以用列表解析式来替代a = [x for x in s1 if x in s2]print(a)

作用域


作用域法则

  • 过度的使用全局变量通常是糟糕的事情
  • 在代码中变量名被赋值的位置决定了这个变量名能被访问到的范围。
  • 一个在def之外被赋值的变量x与在这个def之中赋值的变量x是完全不同的变量
  • 函数的作用域有助于防止程序之中变量名的冲突,并且有助于函数成为更加独立的程序单元
  • 函数定义了本地作用域,模块定义了全局作用域
  • 全局作用域的作用范围仅限于单个文件
  • 当你在python中听到全局的 ,你就应该想到模块
  • 每次对函数的调用都创建了一个新的本地作用域。p417,待定
  • 赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量。如果需要给一个在函数内部却位于模板文件顶层的变量名赋值,需要在函数内部通过global语句声明。如果需要给位于一个嵌套的def中的名称赋值,通过nonlocal声明。

  • 一个函数内部的任何类型的赋值 都会把一个名称划定为本地的。这包括=语句,import中的模块名称,def中的函数名称,函数参数名称等。
  • 原处改变对象并不会把变量划分为本地变量,实际上只有对变量名称赋值才可以。例如,如果变量名L在模块的顶层被赋值为一个列表,在函数内部的像L.append(x)这样的语句并不会将L划分为本地变量,而L=x可以。

变量名解析:LEGB原则

变量名引用分为三个作用域进行查找:首先是本地,之后是函数内,之后全局,最后内置

函数能够在函数内部以及全局作用域直接使用变量名,但是必须声明为非本地变量和全局变量 去改变其属性

nonlocal声明也可以迫使名称映射到函数内部的作用域中。


作用域实例

x = 99           #global全局的,x和funcdef func(y):     #y,z都是本地的,local    z = x + y    #x还是global    return zprint(func(1))    #func在这里体现,终端不用print

z是通过=赋值的,而y是由于参数总是通过赋值来进行传递的。

变量名隔离机制背后的意义就在于本地变量是作为临时的变量名 只有在函数运行时才需要他们。不会与模块空间内的变量名冲突。


内置作用域

x = 88def func():    x = 99func()print(x)    #88

如果在def内部不增加global或nonlocal声明的话,是没有办法在函数内部改变函数外部的变量的。


global语句

它是一个命名空间的声明。

x = 88def func():    global x    x = 99func()print(x)   #99
def add_b():    global  b    #这里加个global,就是说他是全局变量了,等于全局下b=42    b = 42    def do_global():        global  b     #如果把前面的global b引掉,这里的global可以修改为nonlocal,结果一样        b = b + 10        print(b)    do_global()    print(b)add_b()-------5252

最小化全局变量

没看明白,意思就是少用全局变量肯定对,试试通过传递函数然后返回值来 替代一下


最小化文件间的修改

在文件间进行通信的最好的办法就是通过调用函数,传递参数,然后得到其返回值。在这个特定的情况下,我们最好使用accessor函数去管理这种变化。


其他访问全局变量的方法

关于模块


作用域和嵌套函数

嵌套作用域的细节

先是函数内,然后嵌套的,然后全局,然后内置

嵌套作用域举例

x = 99def f1():   x = 88   def f2():      print(x)   f2()f1()   #88

工厂函数

根据要求的对象,这种行为有时候也叫闭合(closure)或者工厂函数。P428

一个能够记住嵌套作用域的变量值的函数,尽管那个作用域已经不存在了。

书上说,这是一种相当高级的技术,除了那些拥有函数式编程背景的程序员们,以后在实际使用中也不会用到

使用默认参数来保留嵌套作用域的状态

最好的处方就是简单的避免在def中嵌套def,这会让程序更加简单

>>> def f1():...     x = 88...     f2(x)... >>> def f2(x):...     print(x)... >>> f1()88

如果使用这样的办法来解决嵌套,你几乎都可以忘记python的嵌套作用域,除非需要编写工厂函数,至少对def是这样。lambda对于def的嵌套是十分自然的,他常常依赖于嵌套作用域。

嵌套作用域和lambda

19章介绍lambda

nonlocal语句

如果我们在nested中把tester作用域中的state声明为一个nonlocal,我们就可以在nested函数中修改它了,即便我们通过名称F调用返回的nested函数时,tester函数已经返回退出了。

>>> def tester(start):...     state = start...     def nested(label):...             nonlocal state...             print(label,state)...             state += 1...     return nested... >>> F = tester(0)>>> F('spam')spam 0>>> F('ham')ham 1>>> F('eggs')eggs 2

注意:

  • 当执行一条nonlocal语句时,nonlocal名称必须已经在一个嵌套的def作用域中赋值过,否则错误。()
def tester(start):    def nested(label):        nonlocal state      #Nonlocals must already exist in enclosing def!        state = 0        print(label,state)    return nested    #SyntaxError:no binding for nonlocal 'state' found
  • nonlocal限制作用域查找仅为嵌套的def,nonlocal不会再嵌套的模块全局作用域所有def之外的内置作用域中查找
>>> spam = 99>>> def tester():...     def nested():...             nonlocal spam...             print('Current=',spam)...             spam += 1...     return nested...  File "<stdin>", line 3SyntaxError: no binding for nonlocal 'spam' found
>>> b = 1>>> def ss(a):...     c = a+b...     print(c)...>>> print(b)1>>> ss(10)11