【Python学习】python函数

2021/12/3 11:06:34

本文主要是介绍【Python学习】python函数,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

无参,无返回值函数

def test1():
    print("我是无参无返回值函数")


test1()

有参数,无返回值函数: 需要动态的调整函数体中某一个处理信息,则可以以参数的形式接收到相关数据

def test2(num):
    print(num ** 1)
    print(num ** 2)
    print(num ** 3)


test2(3)

有参数,有返回值函数:需要动态的调整函数体中某一个处理信息,则可以以参数的形式接收到相关数据,并且函数执行完成后会返回一个值

def test3(num):
    a = num +1
    return a


result = test3(4)
print(result)

有参数函数:需要动态调整函数体中多个处理信息时,则可以以逗号做分割,接收多个参数

def test4(num1, num2):
    print(num1 + num2)


test4(3,4)  # 直接输入实参,形参和实参一一对应


test4(num2=5, num1=4) # 按照关键字传递参数,不是按照参数顺序传递参数的

不定长参数函数,需要在形参前加个“*”,即是元组做参数

def test5(*t):
    print(t, type(t))
    result = 0
    for i in t:
        print(i)
        result += i
    print(result)


test5(1,2,3,4,5)

不定长参数函数,需要在形参前加个“**”,即是类似字典做参数,在调用函数时必须以关键字的形式输入参数

def test6(**kwargs):
    print(kwargs, type(kwargs))


test6(name="larry", age=18, sex="男")

参数的拆包和装包

装包:把传递的参数,包装成一个集合,称之为“装包”

def mySum(a,b,c,d):
    print(a + b + c + d)

def test7(*args):
    # 装包, *args代表是拆包,代表一个一个的数据,args代表是装包,代表是一个整体
    print(args)
    # 拆包,应该使用一个*用于拆包操作, 不用*用于装包操作
    print(*args)
    print(args[0],args[1], args[2], args[3])
    mySum(*args)

test7(1,2,3,4)

拆包:把集合参数,再次分解成单独的个体,称之为“拆包”

def mySum(a,b,c):
    print(a)
    print(b)
    print(c)

def test8(**kwargs):
    # 装包, **kwargs代表是拆包,代表一个一个的数据,kwargs代表是装包,代表是一个整体
    print(kwargs)
    # 拆包,应该使用两个**用于拆包操作, 不用*用于装包操作
    # print(**kwargs)  # 不可以直接打印这个**kwargs,要有接收对应的函数和参数
    mySum(**kwargs)

test8(a="sz", b=18, c="男")   # 调用的时候,也要输入对应的keyword才可以,否则会报错,找不到对应的keyword
# 函数返回值
def test9(a,b):
    he = a + b
    cha = a - b
    return (he, cha)

# res是一个集合
res = test9(4, 5)
# 拆包:
he, cha = test9(4, 5)
print(res)
# res集合拆包
print(res[0], res[1])
print(he, cha)

=======================函数的描述=

# 一般函数的描述,需要说明如下几个信息:函数的功能,参数的含义、类型、是否可以省略、默认值,返回值的含义、类型
def mySum(a, b=1):
    """
    计算两个说的和,以及差
    :param a: 数值1,数值类型,不可选,没有默认值
    :param b: 数值2,数值类型,可选,默认值:1
    :return: 返回计算的结果,元组类型:(和,差)
    """
    he = a + b
    cha = a - b
    return (he, cha)

help(mySum)

#------------------------函数的高级用法------------------------

偏函数:当我们写一个参数比较多的函数时,如果有些参数,大部分场景下都是一个固定的值,那么为了简化使用,就可以创建一个新函数,指定我们要使用的函数的某个参数,为某个固定的值,这个新函数就是“偏函数”

import functools
def test10(a,b,c,d=1):
    res = a + b + c + d
    print(res)

# test10(1,2,3)
#
# # 再定义一个偏函数
# def test11(a,b,c,d=2):
#     test10(a,b,c,d)
#
# test11(1,2,3)

# 使用python自带的一个功能,通过functools模块的partial类来创建一个偏函数,不指定参数的值
newFunc = functools.partial(test10, c=5, d=2)
newFunc(1,2)  # 这个就是新的偏函数,只要输入两个参数就可以了,其他参数使用默认的固定的值

# 偏函数的使用场景,比如int()函数,int()函数有个参数是base,用于指定使用哪个“进制”进行转换成int整数,将数值字符串以某一个进制进行转换
numStr = "10010"

# 导入functools模块,使用里面的partial方法,指定进制base=xx,然后产生一个偏函数
import functools
intTransfer = functools.partial(int, base=16)
res = intTransfer(numStr)
print(res)

======================高阶函数=

高阶函数,如果一个函数的参数能够接收一个函数,那么这个函数就叫高阶函数

l = [{"name":"sz", "age":18}, {"name":"sz2", "age":19}, {"name":"sz3", "age":18.5}]
# 定义个对于l列表选择什么字段进行排序的函数,这个函数会接收l列表中的每个元素
def getKey(x):
    return x["name"]

result = sorted(l, key=getKey, reverse=-1)
print(result)

高阶函数的实例

def caculate(num1, num2, caculateFunc):
    result = caculateFunc(num1, num2)
    print(result)

def sum(a, b):
    return a + b

def jianfa(a, b):
    return a - b

caculate(num1=6, num2=2, caculateFunc=jianfa)

======================返回函数=

返回函数:是指一个函数内部,它返回的数据是另外一个函数,把这样的操作成为“返回函数”

案例:根据不同参数,获取不同操作,做不同计算

def getFunc(flag):
    # 1.再次定义几个函数
    def sum(a, b, c):
        return a + b + c

    def jian(a, b, c):
        return a - b - c

    # 2.根据不同的flag的值,来返回不同的操作函数
    if flag == "+":
        return sum   # 返回的是函数sum,而不是调用sum函数,因为没有加()
    elif flag == "-":
        return jian  # 返回的是函数jian,而不是调用jian函数,因为没有加()

backFunc = getFunc("-")  # 参数传入flag是“+”,返回的是sum函数,flag是“-”,返回的是jian函数
print(backFunc, type(backFunc))
res = backFunc(1,2,3)  # backFunc是个返回函数,那么就可以调用这个函数,并传入参数
print(res)

======================匿名函数=

匿名函数,也称“lambda函数”,顾名思义就是没有名字的函数

newFunc2 = lambda x, y : x + y
res = newFunc2(1,2)
print(res)


l = [{"name":"sz", "age":18}, {"name":"sz2", "age":19}, {"name":"sz3", "age":18.5}]

# 定义个对于l列表选择什么字段进行排序的函数,这个函数会接收l列表中的每个元素
# def getKey(x):
#     return x["name"]

result = sorted(l, key=lambda x : x["age"])
print(result)

======================闭包=

在函数嵌套的前提下,内层函数引用了外层函数的变量或参数,外层函数又把内层函数当作返回值进行返回

那么,将 这个内层函数+所引用的外层变量,称为"闭包"

def test11():
    a = 10
    def test12():
        print(a)

    return test12

newFunc3 = test11()
newFunc3()

应用场景:外层函数,根据不同的参数,来生成不同作用功能的函数

案例:根据配置信息,生成不同的分割线函数

def line_config(content, length):
    def line():
        print(("-" * (length // 2)) + content + ("-" * (length // 2)))

    return line

newFunc4 = line_config("aaaa", 20)
newFunc4()

newFunc5 = line_config("bbbb", 10)
newFunc5()

通过闭包修改外层函数的变量,必须使用nonlocal关键字

def test13():
    num = 1
    def test14():
        nonlocal num
        num = 6
        print(num)

    print(num)
    test14()
    print(num)

    return test14

newFunc5 = test13()
newFunc5()

闭包注意2:

def test15():
    a = 1
    def test16():
        print(a)

    a = 2
    return test16

newFunc6 = test15()
newFunc6()

闭包,更加复杂的例子

def test17():

funcs = []

for i in range(1,4):

def test18():

print(i)

funcs.append(test18)

return funcs

newFuncs = test17()

print(newFuncs)

newFuncs0

newFuncs1

newFuncs2

def test17():
    funcs = []
    for i in range(1,4):
        def test18(num):
            def inner():
                print(num)
            return inner
        funcs.append(test18(i))  # 这个代表,添加的是返回的inner函数,以及对应i的值
    return funcs

newFuncs = test17()
print(newFuncs)
newFuncs[0]()
newFuncs[1]()
newFuncs[2]()

=========================函数装饰器=

作用:在函数名和函数体不改变的前提下,给一个函数附加一些额外代码

案例:发说说,发图片

1.定义两个函数

1.定义两个函数

def checkLogin(func):   # 装饰器函数,为了对于fss()和ftp()函数增加一些额外的小功能,可以定义一个装饰器函数
    def inner():
        print("登录验证...")  # 增加额外的功能代码
        func()   # 传入的函数
    return inner  # 返回内部函数,此内部函数为传入的函数增加了额外的功能代码

#python的语法糖模式,其实就是设计模式,类似调用了checkLog(func)函数并反应一个内部函数,
# 且此返回的函数名字与踹人的函数名字是一样的
@checkLogin   # @checkLogin语法糖,返回一个与下面函数一样的名字的函数,并将此函数额外增加了其他的功能代码
def fss():
    print("发说说")
# fss = checkLogin(fss)

#python的语法糖模式,其实就是设计模式,类似调用了checkLog(func)函数并反应一个内部函数,
# 且此返回的函数名字与踹人的函数名字是一样的
@checkLogin   # @checkLogin语法糖,返回一个与下面函数一样的名字的函数,并将此函数额外增加了其他的功能代码
def ftp():
    print("发图片")
# ftp = checkLogin(ftp)


# 2.相关的逻辑代码
btnIndex = 1
if btnIndex == 1:
    fss()
else:
    ftp()

总结:需要将功能函数的部分,与业务逻辑代码的部分,进行分开

发说说,发图片,必须有一个前提,就是,用户必须登录之后

登录验证的操作

1.直接在业务逻辑代码里面去修改,添加一个验证操作:弊端如下:

因为业务逻辑代码非常多,所以,就造成了,每一份,逻辑代码,在调用,具体的功能函数之前都需要,去做一个登录验证,

代码冗余度,就比较大,而且代码的复用性比较差,代码的维护性比较差

2.直接在功能函数里面去修改,方便代码的重用: 这样也有一点问题,登录验证的代码重复了

改善方式:再定义一个登录验证的函数checkLogin(),然后在发说说和发图片的函数里面调用checkLogin()的函数即可

==============有参数的装饰器,和不定长度的装饰器=

def zsq(func):
    def inner(*args, **kwargs):
        print("_" * 30)
        res = func(*args, **kwargs)
        return res
    return inner

@zsq
def pnum1(num1, num2, num3):
    print(num1, num2, num3)
    return num1 + num2 + num3    # 增加功能函数的返回值,那装饰器也要写成一直的形式

@zsq
def pnum2(num):
    print(num)
    return num

@zsq
def pnum3(*args, **kwargs):
    print(*args, **kwargs)

res1 = pnum1(1,2, num3=666)   # 执行这里的pnum1()函数,就是执行inner函数
res2 = pnum2(999)             # 执行这里的pnum2()函数,就是执行inner函数
res3 = pnum3(1,2,3,4,5,56,6)  # 执行这里的pnum3()函数,就是执行inner函数
print(res1,res2,res3)         # 打印查看返回值

==============返回装饰器的函数,以及通过参数控制装饰器里面的参数值=

def getZsq(char):                           # 返回装饰器函数,是个固定的格式,通过参数来控制,装饰器的内部函数里面的参数值
    def zsq(func):                          # 装饰器函数,也是个固定的格式
        def inner(*args, **kwargs):         # 闭包返回的函数,也是个固定的格式
            print(char * 30)
            res = func(*args, **kwargs)     # 功能函数有返回值的固定写法,也是个固定的格式
            return res                      # 返回功能函数的值
        return inner                        # 返回增加新功能的内部功能函数,也是个固定的格式
    return zsq                              # 返回里面的装饰器,也是个固定的格式


@getZsq("*_")        # 调用返回装饰器的函数,并传入控制装饰器内部函数需要的参数值
def f1(num):
    print("666", num)
    return num

res1 = f1(2)
res2 = f1(3)
print(res1, res2)

在这里插入图片描述

=========================python生成器=

迭代器:是一个特殊的迭代器(迭代器的抽象层次更高),所以,拥有迭代器的特性:惰性计算数据,节省内存;能够记录状态,

并通过next()函数,访问下一个状态,具备可迭代特性

迭代器,相当于是一个生产数据的方式而已,如果需要什么数据,直接调用一个函数,生成一个数据即可

1.创建生成器的方式:生成器表达式,把列表推导式的[]修改成()

l1 = [i for i in range(1,10) if i % 2 == 0]    # 这是列表[]的推导式,会把所有的数据都加载到内存里面
l2 = (i for i in range(1,20) if i % 2 == 0)    # 这是列表[]修改成()就变成生成器表达式了,这个表达式的结果就是一个生成器的对象
print(l1)
print(l2)
print(l2.__next__())
print(l2.__next__())  # 迭代器会记录当前的状态位置,知道下次到什么位置,取什么数据,不会一下子把所有的数据都加载到内存里
print(next(l2))       # next(l2)与l2.__next__()是一样的功能,获取下一个的数据
for i in l2:
    print("for迭代:",i)

在这里插入图片描述

2.通过生成器函数,产生生成器,函数中包含yield语句,这个函数的执行结果就是“生成器”

yield语句,可以去阻断当前的函数执行,然后,当使用next()函数,或者,next(),都会让函数继续执行,然后,当执行到下一个yield语句的时

候,又会被暂停

def test():
    yield 1
    print("a")

    yield 2
    print("b")

    yield 3
    print("c")

    yield 4
    print("d")

g = test()
print(g)
print(g.__next__())
print(g.__next__())
print(g.__next__())

在这里插入图片描述

另外一种生产器的写法,for循环

def test():
    for i in range(1,10):
        yield i

g = test()
print(g)
print(g.__next__())
print(next(g))
print(g.__next__())
print(next(g))

在这里插入图片描述

=================生成器的send()方法=

send()方法,send()方法有一个参数,指定的是上一次被挂起的yield语句的返回值,相比.next()方法,可以额外的给yield语句传值

注意第一次调用 t.send(None)

def test():
    res1 = yield 1
    print(res1)

    res2 = yield 2
    print(res2)

    res3 = yield 3
    print(res3)

g = test()
print(g.send(None))   # 首次使用send()方法,参数必须是None,
print(g.__next__())
print(g.send("000"))

在这里插入图片描述

==============生成器的关闭=

# 关闭生成器的方法,g.close()
# 先写一个生成器的函数
def test():
    yield 1
    print("a")

    yield 2
    print("b")

    yield 3
    print("c")

# 通过生成器函数,先生成一个生成器g
g = test()

# 下面可以对于生成器g进行操作
print(g.__next__())
print(g.__next__())
g.close()   # 通过生产器的close()方法,意思就是将生成器的状态指导生成器的最后,再调用的时候就会报错StopIteration
print(g.__next__())

================生成器的注意事项=

生成器,如果遇到return语句会怎么样,另外能遍历几次

1.生成器,在执行过程中,一旦遇return语句,会立即停止,并报错StopIteration,并输入return后面的值

def test1():
    yield 1
    print("aa")

    # return 10

    yield 2
    print("bb")

    yield 3
    print("cc")

# 通过生成器函数,先生成一个生成器g
g = test1()

# 下面可以对于生成器g进行操作
print(g.__next__())
print(g.__next__())  # 当执行这个代码时就会执行return语句了,就会报错StopIteration 并返回 return 后的值
print(g.__next__())

2.生成器值能遍历1次,如果想再遍历,还需要再拿到生成器

def test2():
    yield 1
    print("aaa")

    # return 10

    yield 2
    print("bbb")

    yield 3
    print("ccc")

# 通过生成器函数,先生成一个生成器g
g = test2()

for i in g:    # for遍历生成器时,能够将生成器里面的最后yield语句下面的代码执行完
    print(i)

print("当前执行的位置xxxxxxxx,下面代码不会执行")
for i in g:    # 当第二次遍历生成器时就不会执行了,前面的print()函数代表是执行的位置,要想使用还需要	
	print(i)   # 再获取一次生成器
	

========递归函数=

在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://www.www.zyiz.net/i/ll/?i=c447b4570a194120ab93dd8e04a85b28.png?,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZ2FvZ3Nm,size_20,color_FFFFFF,t_70,g_se,x_16

在这里插入图片描述

====================递归函数=

递归函数:函数A内部,继续调用函数A

递归函数:先有传递,即询问;后有回归,传递值

# 案例:求一个数的阶乘,比如9的阶乘:9! = 9 * 8 * 7 * 6 * 5 * .... * 2 * 1
# 功能:如果是不直接知道结果的数据,就进行分解,
def jieCheng(n):
    if n == 1:      # 这里就是传递结束的位置条件,也是回归的开始位置条件
        return 1
    # 下面肯定是 n != 1的情况
    return n * jieCheng(n-1)

result = jieCheng(3)
print(result)

======================函数的作用域=

python不存在块级作用域的,比如if,while等,其他语言是有块级作用域(块外不能访问)

a = 10                  # a是G,全局变量,作用域是整个文档内
def test3():
    b = 9               # b是E,外部嵌套函数的命名空间
    print(b)
    def test4():
        c = 8           # c是L,局部变量
        print(b)
        return c
    return test4
print(__name__)         # __name__是B, python内建变量,每个文件里面都可以使用
print(a)
newFunc = test3()
res = newFunc()
print(res)

在这里插入图片描述
在这里插入图片描述



这篇关于【Python学习】python函数的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程