python11-函数合集

目录

1、函数定义

2、函数参数

3、作用域

4、闭包

5、装饰器

6、lambda表达式

7、生成器

8、递归


1、函数定义

使用 def 语句来定义函数,紧跟着的是函数的名字,后面带一对小括号,冒号下面就是函数体,函数体是一个代码块,也就是每次调用函数时将被执行的内容。

>>> def myfunc(name, times):
...     for i in range(times):
...         print(f"I love {name}.")
...
>>> myfunc("Python", 5)
I love Python.
I love Python.
I love Python.
I love Python.
I love Python.

有时候,我们可能需要函数干完活之后能给一个反馈,这在 BIF 函数中也很常见,比如 sum() 函数会返回求和后的结果,len() 函数会返回一个元素的长度,而 list() 函数则会将参数转换为列表后返回。只需要使用 return 语句,就可以让咱们自己定制的函数实现返回。

>>> def div(x, y):
...     z = x / y
...     return z
...
>>> div(4, 2)
2.0

2、函数参数

位置参数:参数位置固定,实参按照形参传递。关键字参数:指定具体值。默认参数:如果没有传入实参,就使用默认参数,如果使用默认参数把他们放在最后。

>>> def myfunc(s, vt, o):
...    return "".join((o, vt, s))
...
>>> myfunc("我", "打了", "小甲鱼")
'小甲鱼打了我'
>>> myfunc("小甲鱼", "打了", "我")
'我打了小甲鱼'
#位置参数

>>> myfunc(o="我", vt="打了", s="小甲鱼")
'我打了小甲鱼'
#关键字参数

>>> myfunc(o="我","打了","小甲鱼")
SyntaxError: positional argument follows keyword argument
"""同时使用位置参数和关键字参数,要注意位置参数必须在关键字参数前"""

>>> def myfunc(s="苹果", vt, o="小甲鱼"):
        
SyntaxError: non-default argument follows default argument
"""使用默认参数必须放在最后面"""
>>> def myfunc(vt, s="苹果", o="小甲鱼"):
...     return "".join((o, vt, s))
... 
>>> myfunc("拱了")
'小甲鱼拱了苹果'
#默认参数放最后

对于只能使用位置参数的函数,我们举例子为abs()函数,例如我们使用help(abs)和help(sum)帮助文档我们可以看到函数的参数里有反斜杠。这表示反斜杠左侧必须是位置参数,不能是关键字参数,而对于反斜杠右侧就随意了。

>>> help(abs)
Help on built-in function abs in module builtins:
    
abs(x, /)
    Return the absolute value of the argument.

>>> help(sum)
Help on built-in function sum in module builtins:
    
sum(iterable, /, start=0)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers
    
    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.
>>> abs(-1.5)
1.5
>>> abs(x = -1.5)
Traceback (most recent call last):
  File "", line 1, in 
    abs(x = -1.5)
TypeError: abs() takes no keyword arguments

对于只能使用关键字参数,利用*号、参数 a 既可以是位置参数也可以是关键字参数,但参数 b 和参数 c 就必须是关键字参数。

>>> def abc(a, *, b, c):
...     print(a, b, c)
>>> abc(1,2,3)
Traceback (most recent call last):
  File "", line 1, in 
    abc(1,2,3)
TypeError: abc() takes 1 positional argument but 3 were given
>>> abc(1,b=2,c=3)
1 2 3
>>> abc(a=1,b=2,c=3)
1 2 3

收集参数:不限制参数,即在形参前面加*,形参使用叫打包,实参使用叫解包。即指定一个参数,调用的时候可以传回任意数量的参数。如果收集参数后面还有指定的其他参数,那么在调用的时候要用关键字参数来指定。收集参数也可以将参数打包成字典,做法是加两个**,对于这种情况传递参数只能用关键字参数,因为字典的键值对

def myfunc(*arge):
    print("有%d个参数。"%len(arge))    #print("有{}个参数".format(len(arge)))
    #print(f"有{len(arge)}个参数")
    print("第二个参数是:%s"%arge[1])    #print("第二个参数是{}".format(arge[1]))
    #print(f"第二个参数是{arge[1]}")

    
myfunc("小甲鱼","不二如是")
有2个参数。
第二个参数是:不二如是

def myfunc(*args,a,b):
    print(args,a,b)
  
myfunc(1,2,3,a = 4,b = 5)
(1, 2, 3) 4 5

>>> def myfunc(a, *b, **c):
...     print(a, b, c)
... 
>>> myfunc(1, 2, 3, 4, x=5, y=6)
1 (2, 3, 4) {'x': 5, 'y': 6}

同样*和**也可以用在实参上,在实参上对应的解包。

>>> args = (1, 2, 3, 4)
>>> def myfunc(a, b, c, d):
...     print(a, b, c, d)
... 
>>> myfunc(*args)
1 2 3 4

>>> args = {'a':1, 'b':2, 'c':3, 'd':4}
>>> myfunc(**args)
1 2 3 4

3、作用域

局部作用域:一个变量定义在函数里面,作用域仅限于函数,为局部变量。

全局作用域:在任何函数外部定义的变量,作用域是全局的。

注意下面的x并非同一个变量,只是由于作用域不同,同名不同样。

>>> x = 880
>>> def myfunc():
...     x = 520
...     print(x)
... 
>>> myfunc()
520
>>> print(x)
880

global语句:我们在函数内部无法修改全局变量的值,除非使用global语句破除限制。

>>> x = 880
>>> def myfunc():
...     global x
...     x = 520
...     print(x)
... 
>>> myfunc()
520
>>> print(x)
520

嵌套函数,想要调用内部的函数必须先通过外部的函数

>>> def funA():
...     x = 520
...     def funB():
...         x = 880
...         print("In funB, x =", x)
...     funB()
...     print("In funA, x =", x)
... 
>>> funA()
In funB, x = 880
In funA, x = 520

nonlocal语句:通常我们无法在嵌套函数的内部修改外部函数变量的值,除非使用 nonlocal 语句破除限制:

>>> def funA():
...     x = 520
...     def funB():
...         nonlocal x
...         x = 880
...         print("In funB, x =", x)
...     funB()
...     print("In funA, x =", x)
... 
>>> funA()
In funB, x = 880
In funA, x = 880

LEGB规则:

  • L 是 Local,是局部作用域
  • E 是 Enclosed,是嵌套函数的外层函数作用域
  • G 是 Global,是全局作用域
  • B 是 Build-In,也就是内置作用域

即:局部-嵌套-全局-内置

"""在局部作用域中找到e"""
def f():
    def h():
        e = 3
        print(f"e={e}")
    h()

    
f()
e=3
"""在嵌套函数外的嵌套作用域中找到e"""
def f():
    e = 2
    def h():
        print(f"e={e}")
    h()

    
f()
e=2
"""从全局作用域中找"""
e=1
def f():
    def h():
        print(f"e={e}")
    h()

f()
e=1

"""从内置函数中找到e"""
from math import e
def f():
    def h():
        print(f"e={e}")
    h()

    
f()
e=2.718281828459045

4、闭包

>>> def funA():
...     x = 520
...     def funB():
...         print(x)
...     return funB
>>> funA()
.funB at 0x0000014C02684040>
>>> funA()()
520
>>> funny = funA()
>>> funny
.funB at 0x0000014C02684550>
>>> funny()
520

LEGB规则中的E,对于嵌套函数来说,外层函数的作用域是会通过某种形式保存下来,尽管函数已经调用完了,但是外层作用域的变量会保存下来,不会像局部作用域那样调用完就消失。

闭包:利用嵌套函数实现工厂的功能。

  1. 利用嵌套函数的外层作用域具有记忆功能这个特性。
  2. 将内层函数作为返回值返回。
>>> def power(exp):
...     def exp_of(base):
...         return base ** exp
...     return exp_of
... 
>>> square = power(2)
>>> cube = power(3)
>>> square
.exp_of at 0x000001CF6A1FAF70>
>>> square(2)
4
>>> square(5)
25
>>> cube(2)
8
>>> cube(5)
125

exp接收的是power传入的值,然后return返回的是内部嵌套exp_of 的引用,所以可以利用这个引用进行计算,以下代码为带记忆功能的函数。利用内层函数能够记住外层函数的作用域这个特性,并且使用nonlocal语句修改外层函数作用域里面的变量。

def outer():
    x = 0
    y = 0
    def inner(x1,y1):
        nonlocal x,y
        x+=x1
        y+=y1
        print(f"现在,X={x},Y={y}")
    return inner

move = outer()
move(1,2)
现在,X=1,Y=2
move(-2,-2)
现在,X=-1,Y=0

5、装饰器

把函数作为参数给另一个函数,类似 f 字符串,避免对之前的代码进行改动,直接外层进行添加。详细了解参照知乎抖音和小甲鱼相关介绍。

def myfunc():
    print("正在调用函数")
def report(func):
    print("开始调用")
    func()
    print("调用完毕")
    
report(myfunc)
开始调用
正在调用函数
调用完毕

import time
    
def time_master(func):
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒。")
    return call_func
    
@time_master
def myfunc():
    time.sleep(2)
    print("I love FishC.")
    
myfunc()

6、lambda表达式

一行流表达式。传统定义的函数,函数名就是一个函数的引用,而 lambda 表达式,整个表达式就是一个函数的引用。

lambda 是一个表达式,因此它可以用在常规函数不可能存在的地方。如下y[0]是lambda表达式的函数然后小括号里面传参数。

>>> def squareX(x):
...     return x * x
...
>>> squareX(3)
9
"""同上"""
>>> squareY = lambda y : y * y
>>> squareY(3)
9

>>> y = [lambda x : x * x, 2, 3]
>>> y[0](y[1])
4
>>> y[0](y[2])
9

利用map函数和filter函数,map函数第一个参数要求是一个函数的引用,第二个参数是序列类型,然后把第二个参数挨个传给第一个参数,运算之后构成一个迭代器。filter对指定的对象的每一个元素进行计算并返回结果为真的元素,回顾python-09。

>>>  list(mapped = map(lambda x : ord(x) + 10, "FishC"))
[80, 115, 125, 114, 77]
>>> list(filter(lambda x : x % 2, range(10)))
[1, 3, 5, 7, 9]

7、生成器

让函数退出后还能保留状态,一个是全局变量(污染空间)一个是闭包(麻烦),还有生成器。

在 Python 中,使用了 yield 语句的函数被称为生成器(generator)。定义一个生成器,很简单,就是在函数中,使用 yield 表达式代替 return 语句即可。

生成器一次只下一个蛋。

>>> def counter():
...     i = 0
...     while i <= 5:
...         yield i
...         i += 1
>>> counter()

>>> for i in counter():
...     print(i)
... 
0
1
2
3
4
5

"""斐波那契数列"""
>>> def fib():
...     back1, back2 = 0, 1
...     while True:
...         yield back1
...         back1, back2 = back2, back1 + back2
... 
>>> f = fib()
>>> next(f)
0
>>> next(f)
1
>>> next(f)
1
>>> next(f)
2
>>> next(f)
3
>>> next(f)
5
>>> next(f)
8
>>> next(f)
13
>>> next(f)
21

只要我们调用 next(f),就可以继续生成一个新的斐波那契数,由于我们在函数中没有设置结束条件,那么这样我们就得到了一个永恒的斐波那契数列生成器。

8、递归

函数自己调用自己的过程。要让递归正常工作,必须要有一个结束条件,并且每次调用都将向着这个结束条件推进。

下面代码会持续输出 “AWBDYL”,直到你把 IDLE 关闭或者使用 Ctrl + c 快捷键强制中断执行。

>>> def funC():
...     print("AWBDYL")
...     funC()
... 
>>> funC()
AWBDYL
AWBDYL
AWBDYL
AWBDYL
AWBDYL
AWBDYL
AWBDYL
AWBDYL
AWBDYL
AWBDYL
...

求一个数的阶乘

"""迭代"""
>>> def factIter(n):
...     result = n
...     for i in range(1, n):
...         result *= i
...     return result
... 
>>> factIter(5)
120
>>> factIter(10)
3628800

"""递归"""
>>> def factRecur(n):
...     if n == 1:
...         return 1
...     else:
...         return n * factRecur(n-1)
... 
>>> factRecur(5)
120
>>> factRecur(10)
3628800

"""迭代-斐波那契数列"""
>>> def fibIter(n):
...     a = 1
...     b = 1
...     c = 1
...     while n > 2:
...         c = a + b
...         a = b
...         b = c
...         n -= 1
...     return c
... 
>>> fibIter(12)
144

"""递归-斐波那契数列"""
>>> def fibRecur(n):
...     if n == 1 or n == 2:
...         return 1
...     else:
...         return fibRecur(n-1) + fibRecur(n-2)
... 
>>> fibRecur(12)
144

学习来源于小甲鱼教学

你可能感兴趣的:(python)