十六、python里的函数

十六、python里的函数

python里函数分为内置函数与自定义函数
内置函数:如int(),str(),len()等,所有的内置函数参考https://docs.python.org/3/library/functions.html

自定义函数的定义与调用(重点)

def funct():              # 函数名(),括号里可以写参数,也可以不写
    """函数说明或注释"""    # 说明可以不写,大型程序为了程序可读性最好写
    print("xxx")         # 函数代码主体
    print("xxx")         # 函数代码主体
    print("xxx")         # 函数代码主体
    return 0             # 函数返回值,可有可无

funct()   # 调用函数的方式(调用函数也就是执行函数内部的代码)

函数传参格式

定义函数传参格式
def 函数名(形参1,形参2):
    函数体

调用格式:
函数名(实参1,实参2)

函数参数传递的顺序和个数必须一致

实例

def wash(a, b, c):
    print("加水{}升".format(a))
    print("搓洗{}分钟".format(b))
    print("脱水{}分钟".format(c))
wash(3, 40, 10)
wash(b=40, a=3, c=10)  # 关键字参数可以换位置

默认参数(缺省值)

含义:为参数提供默认值,调用函数时可不传该默认参数的值
注意:所有的位置参数必须出现在默认参数前,包括函数定义和调用

def connect_ssh(host,usr,password,port=22): # port=22为默认参数
    print(host, usr, password, port)

host = input("input host:")
user = input("input user:")
password = input("password")
connect_ssh(host,user,password,33) # 不用再传port的值,默认就是22,也可以传一个新的值替代22
#设置默认值,没有传值会根据默认值来执行代码,传了值会根据传入的值来执行代码

可变参数

含义:传入参数的数量是可以改变的,可以传入多个,也可以不传
格式:
def func(*args):
    print(args)  # 以元组的形式接收
func(1,2,3,4,5)

案例
def funct1(*args): # args可改成其他参数名,就是一个形参
    num1 = 0
    for i in args:
        if isinstance(i,int):
            num1 += i
    print(num1)
funct1(1,2,3,4,"a","v")

关键字参数

格式:def func(**kwargs)  #kwargs可改成其他参数名,就是一个形参
作用:可以扩展函数的功能
def func(**kwargs):
    print(kwargs)
    print(type(kwargs))  # 以字典形式接收
func()  # 空字典
func(name='zhangsan',age=18)  # 传值的时候,采用键=值的形式

嵌套函数

实例1

def bbb():
    print("bbb")
    aaa()

def aaa():
    print("aaa")

bbb()

实例2

def aaa():
    print("aaa")

def bbb():
    print("bbb")
    aaa()

bbb()
实例1与实例2都是同样打印出
bbb
aaa

请问下面的代码有没有问题

def bbb():
    print("bbb")
    aaa()

bbb()

def aaa():
    print("aaa")
报错NameError: name 'aaa' is not defined
总结:
函数要先定义才能调用
函数类似一个变量,定义函数就是把函数体内的代码在内存开辟一个空间存放进去,然后可以通过函数名来调用
调用函数其实就是执行函数体内的代码

小结

1.为什么要传参?
每次调用函数可能会有不同的需求,传参就相当于是和函数做交互,传不同的值给函数来实现不同的需求

2.形参和实参

3.位置参数
实参与形参按顺序一一对应

4.关键字参数
在实参里也要写上形参的名字,这样做可以改变顺序

5.默认值参数
大部分情况下值不变,极少数值不一样的情况下可以使用默认值参数。
默认值参数就是不传值就用默认的,传了值就用传的值。

6.可变长参数
参数个数不确定的情况就用可变长参数

函数返回值(重点)

函数的功能要专一,一个函数只能完成一个功能
函数返回值额度作用:把函数的执行结果返回给需要调用的地方
函数return返回的是一个,所以要赋值给一个变量,然后通过调用变量得到返回值
函数返回值写在函数体的最后,因为函数返回值意味着函数的结束

def funct1(*args):
    num1 = 0
    for i in args:
        if isinstance(i,int):
            num1 += i
    return num1		# return返回的值才可以被调用
sum = funct1(1,2,3,4,5,5)
if sum > 10:
    print("大了")
else:
    print("小了")

小结

函数的结果要被其他地方调用,就不要在函数里用print打印,而是用return做成返回值,再把这个返回值赋值给一个变量,让调用者使用这个变量就是在使用这个函数的结果。

函数变量的作用域:全局变量,局部变量

全局变量:函数外部定义的变量,在整个文件中都是有效的
局部变量:函数内部定义的变量,从定义位置开始到函数定义结束位置有效

实例

name="zhangsan"  #全局变量

def change_name():
    name="lisi"  #这个变量只能在函数内生效,也就是局部变量(可以说这个函数就是这个变量的作用域)
    gender="male"
    print(name)

change_name()
print(name)  #打印出zhangsan
print(gender) # 这句会报错,因为它是局部变量,在外面调用不了

global关键字

作用:global可以对全局变量进行修改,也可以在局部作用域中声明一个全局变量

def change_name():
    global name, gender  # 这句可以把name改为全局变量,但不建议这样用,如果多次调用函数,这样很容易混乱,容易与外部的变量冲突
    name="lisi"
    gender="male"
    print(name)

change_name()  # 这句的结果为lisi,调用函数内部的print(name)得到的结果
print(name)   # 这句的结果为lisi
print(gender)  # 可以调用gender变量了,能打印出结果

nonlocal

作用:只能在嵌套函数中使用,用来声明外层的局部变量,,在外部函数先进行声明,内部函数进行nonlocal声明
a=10 #全局变量
def outer():
    a=5  # 局部变量
    def inner():
        a=20
        print("inner函数中a的值",a)
    inner()
    print("outer函数中a的值",a)
outer()

匿名函数

语法:函数名 = lambda 形参 : 返回值(表达式)
调用:结果 = 函数名(实参)

普通函数
def add(a,b):
    return (a+b)
print(add(1,2))
匿名函数
add = lambda a,b:a+b  # a,b就是匿名函数的形参,a+b就是返回值的表达式
# lambda不需要写return来返回值,表达式本身结果就是返回
print(add(1,2))

lambda的参数形式
1.无参数
funa = lambda  :'一杯水'
print(funa())
2.一个参数
funb = lamba name:name
print(funb('zhangsan'))
3.默认参数
func = lamba name,age=18:(name,age)
print(func('zhangsan'))
print(func('zhangsan',20))
fune = lambda a,b,c=10:a+b+c
print(fune(1,2))
print(fune(1,2,3))

递归函数(拓展)

函数可以调用其他函数,也可以调用自己,如果一个函数自己调用自己,就是递归函数,但递归也有次数上限(保护机制),所以递归需要一个结束条件
在计算机中,函数调用通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的。所以递归调用的次数过多,会导致栈溢出。

常用内置函数

import builtins
# print(dir(builtins)) # 查看有哪些函数
# 大写字母开头一般是内置常量名,小写字母开头一般是内置函数名

# abs() 返回绝对值
print(abs(-10))

# sum() 求和
# print(sum(123)) 报错,整型不是可迭代对象,sum函数里面要放可迭代的对象,注意:字符不可以进行相加
print(sum((1,2,3)))  #元祖
print(sum({1,2,3}))  #集合
print(sum([1,2,3]))  #列表

# min() 求最小值
# max() 求最大值
print(min(1,2,3,4))
print(max(1,2,3,4))
print(min(-8,4,key=abs))  # 传入了绝对值函数,则参数就会先求绝对值再取较大值

# zip() 将可迭代对象作为参数,将对象中对应的元素打包成一个个元组
li = [1,2,3]
li2 = ['a','b','c','d']
print(zip(li,li2))
# 第一种方式,通过for循环打印
for i in zip(li,li2):
    print(i)  # 元素会一一对应输出元组,如果元素个数不一致,就按照长度最短的返回
# 第二种方式,转换成列表打印
print(list(zip(li,li2)))
# 注意:必须是可迭代对象


# map() 可以对可迭代对象中的每一个元素进行映射,分别去执行
# map(func,iter1)  func--自己定义的函数, iter1--要放进去迭代的对象,简单来说就是对象中的每一个元素都会去执行这个函数
li = [1,2,3]
def func(a):
    return a * 5
map=map(func,li)
print(map)
# 方法一:
# for i in map:
#     print(i)
# 方法二:
# print(list(map))


# reduce() 先把对象中的两个元素取出,计算出一个值保存着,接下来把计算值跟第三个元素进行计算
# 需要先导包
from functools import reduce
# reduce(function,sequence) function--函数:必须是有两个参数的函数,sequence--序列:必须是可迭代对象
li2=[1,2,3,4]
def add(x,y):
    return x+2*y
res=reduce(add,li2)
print(res)


# 拆包:对于函数中的多个返回数据,去掉元组,列表或字典,直接获取里面数据的过程
tua = (1,2,3,4)
print(tua)
# 方法一:
a,b,c,d = tua
print('a=',a,'b=',b,'c=',c,'d=',d)
# 要求元组内的个数与接收的变量个数相同,对象内有多少个数据就需要定义多少个变量接收,如果接收的变量和元组的数据不一样,就会报错too many values to unpack (expected 2)
# 方法二
a,*b=tua
print('a=',a,'b=',b)
def func(a,b,*args):
    print(a,b)
    print(args,type(args))
func(1,2,3,4,5,6,7)

posted @ 2023-06-21 17:57  村尚chun叔  阅读(65)  评论(0)    收藏  举报