引言

  • 将一段代码集中到一块,起一个名字,下次可以根据这个名字再次使用这个代码块。
  • 作用:
    • 方便代码重用
    • 分解任务,简化程序逻辑
    • 使代码更加模块化

      函数的参数

      所有的传参方式都是传引用,注意列表做参数和数值做参数容易出现的问题。

      单个参数

      多个参数

      ```python

      定义方式

      def funName(arg1, arg2, arg3…): pass

调用方法

funName(arg1, arg2, arg3…) # 形参和实参一一对应 funName(arg2=v2, arg3=v3, arg1=v1) # 指明形参的名称,不用严格按照形参顺序

  1. <a name="ed38d877"></a>
  2. ## 不定长参数
  3. ```python
  4. # 1. 利用元组的拆包装包
  5. def mySum(*args):
  6. print(type(args)) # <class 'tuple'>
  7. print(args) # (1, 2, 3, 4)
  8. print(*args) # 拆包操作 1, 2, 3, 4
  9. for v in args:
  10. # todo ...
  11. """
  12. 装包,将传入的参数装入一个元组中,args就成了一个元组对象
  13. 拆包,将一个元组中的元素拆分出来,*args就成了参数序列
  14. """
  15. # 2. 利用字典的键值对
  16. def myInfo(**args):
  17. print(type(args)) # <class 'dict'>
  18. # todo ...
  19. myInfo(name="MetaTian", age=21)

默认参数

  1. """
  2. 调用某些函数时,可以省略某些参数,采用定义函数时指定的值
  3. 若不省略,则以调用时传入的值为准
  4. """
  5. def sorted(iterable, reverse=False):
  6. pass
  7. new_list = sorted([1, 3, 2, 5])
  8. new_list = sorted([1, 3, 2, 5], True)

返回值

  • 返回语句标志着函数的结束,一个函数最好只有一处返回语句
  • 如果想返回多个数据,可以把数据包装成一个集合,整体返回(列表,元组,字典…)

    1. def funName():
    2. data = {}
    3. # todo...
    4. return data

    偏函数

  • 对于一个默认值较多的函数,有时我们需要重复用到其中的部分默认值,每次指定默认值比较麻烦。

  • 可以将其中的默认值先赋值好,然后封装成一个新的函数,这就是偏函数。 ```python import functools numStr = “100010” res = int(numStr, base=2) print(res) # 34

int2 = functools.partial(int, base=2) # 重新封装,构成偏函数 print(int2(numStr)) # 34

  1. <a name="be10e9dd"></a>
  2. # 高阶函数
  3. - 一个函数的参数可以是另外一个函数
  4. ```python
  5. def calculate(a, b, cal_fun):
  6. print(cal_fun(a, b))
  7. def sum(a, b):
  8. return a + b
  9. def sub(a, b):
  10. return a - b
  11. calculate(2, 3, sum) # 5
  12. calculate(2, 3, sub) # -1

匿名函数

  • lambda表达式
  • 没有名字的函数 ```python “”” lambda arguments: expression 冒号前面是参数,后面是要返回的表达式 “”” res = (lambda x, y : x + y)(1, 2) print(res) # 3

fun = lambda x, y : x + y print(fun(2, 3)) # 5

更多的是配合 map(), reduce()等函数进行使用

  1. <a name="0edb4c85"></a>
  2. # 闭包
  3. - 在函数嵌套定义的前提下
  4. - 内层函数引用了外层函数的变量
  5. - 外层函数把内层函数当做返回值
  6. ```python
  7. def line_config(content, length):
  8. define line():
  9. print(content * length)
  10. return line
  11. line1 = line_config("-", 5);
  12. line2 = line_config("*", 6)
  13. line1(); # -----
  14. line2(); # ******
  • 作用域问题:内层函数要修改外层函数的变量,要使用nonlocal进行声明,否则变量属于内层函数。

    1. def test():
    2. num = 10
    3. def test2():
    4. nonlocal num # test中的 num被修改
    5. num = 666
    6. return test2
  • 当内层函数使用外层的变化量时,注意值的情况 ```python def test(): funs = [] for i in range(1, 4):

    1. def test2():
    2. print(i)
    3. funs.append(test2)

    return funs

“”” 函数在运行时才会去确定变量的值 运行时,索引 i 的值因定义时迭代完成,不再发生变化 细节请参考迭代器部分 “”” myFuns = test() myFuns0 # 3
myFuns1 # 3 myFuns2 # 3

  1. <a name="e97bc1e5"></a>
  2. # 装饰器
  3. - 在调用目标函数之前,对这个函数对象进行**装饰**(增加一些其他功能)。
  4. - 函数的**名字不能改变**。
  5. - 函数体内部的**代码不能发生改变**。
  6. <a name="568d18bd"></a>
  7. ## 使用案例
  8. ```python
  9. def check(func):
  10. def inner():
  11. print("登录验证...")
  12. func()
  13. return inner # 返回装饰后的函数
  14. # 在 fss()和 ftp()执行之前,都会送入 check()进行包装
  15. @check # 只要python解释器执行到了这行代码就会进行装饰执行
  16. def fss():
  17. print("发说说")
  18. # 上面三行等价于 fss = check(fss)
  19. @check
  20. def ftp():
  21. print("发图片")
  22. # 上面三行等价于 ftp = check(ftp)
  23. # 主业务逻辑如下:
  24. flag = 1
  25. if flag == 1:
  26. fss() # 登录验证...
  27. else: # 发说说
  28. ftp()

多个装饰器的调用顺序

  1. def one(func):
  2. print('----1----')
  3. def two():
  4. print('----2----')
  5. func()
  6. return two
  7. def a(func):
  8. print('----a----')
  9. def b():
  10. print('----b----')
  11. func()
  12. return b
  13. @one
  14. @a
  15. def demo():
  16. print('----3----')
  17. demo()
  18. # 运行结果 //从下到上装饰,从上到下执行,分析略
  19. ----a----
  20. ----1----
  21. ----2----
  22. ----b----
  23. ----3----

对带有参数的函数进行装饰

  1. def zsq(funcs):
  2. def inner(*args, **kwargs): # 装包
  3. print("-" * 5)
  4. func(*args, **kwargs) # 拆包
  5. return inner
  6. @zsq
  7. def fun1(n1, n2, n3):
  8. print(n1, n2, n3)
  9. @zsq
  10. def fun2(n):
  11. print(n)
  12. fun1(1, 2, n3=8) # 1 2 8
  13. fun2(3) # 3

对带有返回值的函数进行装饰

  1. def zsq(funcs):
  2. def inner(*args, **kwargs): # 装包
  3. print("-" * 5)
  4. res = func(*args, **kwargs) # 拆包
  5. return res
  6. @zsq
  7. def fun1(n1, n2, n3):
  8. return sum(n1, n2, n3)
  9. fun1(1, 2, 3)

带有参数的装饰器

  1. def getzsq(char):
  2. def zsq (func):
  3. def inner():
  4. print(char * 5)
  5. func()
  6. return inner
  7. return zsq
  8. @getzsq("*")
  9. def f(): # *****
  10. print("666") # 666
  11. @getzsq("-")
  12. def f1(): # -----
  13. print("666") # 666

生成器

  • 是一个特殊的迭代器
  • 特性:
    • 惰性计算数据,节省内存
    • 能够记录状态,通过next()函数,访问下一个状态
  • 使用方式 ```python

    生成器表达式,不是元组推导,没有元组推导式

    l = (i for i in range(1, 10000000) if i % 2) print(type(l)) print(next(l)) # 1 print(next(l)) # 3 for i in l: print(i) # 循环打印出所有满足条件的值

生成器函数

def test(): for i in range(1, 9): yield i g = test() print(next(g)) # 1 print(next(g)) # 2 ```