彻底搞懂python函数2

一、变量作用域

变量起作用的代码范围称为变量的作用域,不同作用域内变量名可以相同,互不影响。

  • 局部变量在函数内部定义的普通变量只在函数内部起作用。当函数执行结束后,局部变量自动删除,不再可以使用。
    局部变量的引用比全局变量速度快,应优先考虑使用。

  • 全局变量可以通过关键字global来定义。这分为两种情况:
    1.一个变量已在函数外定义,如果在函数内需要为这个变量赋值,并要将这个赋值结果反映到函数外,可以在函数内使用global将其声明为全局变量。
    2.如果一个变量在函数外没有定义,在函数内部也可以直接将一个变量定义为全局变量,该函数执行后,将增加一个新的全局变量。

  • 在函数内只引用某个变量的值而没有为其赋新值,如果这样的操作可以执行,那么该变量为(隐式的)全局变量

  • 如果在函数内任意位置有为变量赋新值的操作,该变量即被认为是(隐式的)局部变量,除非在函数内显式地用关键字global进行声明。

>>> def demo():
    global x                 #x被声明为全局变量
    x = 3
    y = 4
    print(x,y)

>>> x = 5
>>> demo()
3  4
>>> x
3               #如果把global x删去则输出5,因为此时上边定义的x为局部变量,只在demo()函数内生效
>>> y           #因为y是局部变量所以在函数外调用会报错
NameError: name 'y' is not defined
>>> del x         #把x删掉
>>> x
NameError: name 'x' is not defined
>>> demo()
3  4
>>> x
3
>>> y
NameError: name 'y' is not defined
  • 如果局部变量与全局变量具有相同的名字,那么该局部变量会在自己的作用域内隐藏同名的全局变量,但函数内部声明的局部变量不会影响到函数外部
>>> def demo():
    x = 3         #创建了局部变量,并自动隐藏了同名的全局变量	

>>> x = 5
>>> x
5                #函数内部声明的局部变量不会影响函数外部
>>> demo()
>>> x             #函数执行不影响外面全局变量的值
5

二、lambda表达式

  • lambda表达式可以用来声明匿名函数,也就是没有函数名字的临时使用的小函数,尤其适合需要一个函数作为另一个函数参数的场合。也可以定义具名函数。
  • lambda表达式只可以包含一个表达式,该表达式的计算结果可以看作是函数的返回值,不允许包含复合语句,但在表达式中可以调用其他函数。
>>> f = lambda x, y, z: x+y+z        #可以给lambda表达式起名字
>>> f(1,2,3)                         #像函数一样调用
6
>>> g = lambda x, y=2, z=3: x+y+z    #参数默认值
>>> g(1)
6
>>> g(2, z=4, y=5)                   #关键参数
11
>>> L = [1,2,3,4,5]
>>> print(list(map(lambda x: x+10, L)))        #模拟向量运算
[11, 12, 13, 14, 15]
>>> L
[1, 2, 3, 4, 5]
>>> data = list(range(20))           #创建列表
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> import random
>>> random.shuffle(data)             #打乱顺序
>>> data
[4, 3, 11, 13, 12, 15, 9, 2, 10, 6, 19, 18, 14, 8, 0, 7, 5, 17, 1, 16]
>>> data.sort(key=lambda x: x)       #和不指定规则效果一样
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data.sort(key=lambda x: len(str(x)))     #按转换成字符串以后的长度排序
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data.sort(key=lambda x: len(str(x)), reverse=True)     #降序排序,两位数在前
>>> data
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

三、生成器函数

  • 包含yield语句的函数可以用来创建生成器对象,这样的函数也称生成器函数
  • yield语句与return语句的作用相似,都是用来从函数中返回值。与return语句不同的是,return语句一旦执行会立刻结束函数的运行,而每次执行到yield语句并返回一个值之后会暂停或挂起后面代码的执行,下次通过生成器对象的__next__()方法、内置函数next()、for循环遍历生成器对象元素或其他方式显式“索要”数据时恢复执行。
  • 生成器具有惰性求值的特点,适合大数据处理。
#编写并使用能够生成斐波那契数列的生成器函数。
>>> def f():
    a, b = 1, 1            #序列解包,同时为多个元素赋值
    while True:
        yield a            #暂停执行,需要时再产生一个新元素
        a, b = b, a+b      #序列解包,继续生成新元素

>>> a = f()                #创建生成器对象
>>> for i in range(10):    #斐波那契数列中前10个元素
    print(a.__next__(), end=' ')
1 1 2 3 5 8 13 21 34 55 

>>> for i in f():         #斐波那契数列中第一个大于100的元素
    if i > 100:
        print(i, end=' ')
        break

144
>>> a = f()               #创建生成器对象
>>> next(a)               #使用内置函数next()获取生成器对象中的元素
1
>>> next(a)               #每次索取新元素时,由yield语句生成
1
>>> a.__next__()          #也可以调用生成器对象的__next__()方法
2
>>> a.__next__()
3
发布了108 篇原创文章 · 获赞 332 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/zag666/article/details/105073301