0
点赞
收藏
分享

微信扫一扫

python语言基础(八)函数

weipeng2k 2022-03-11 阅读 64

函数

函数介绍(熟悉)

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数作用:
提高 应用的模块性 与 代码的复用

自定义函数(掌握)

定义规则:

  • 函数代码块以 def 关键词 开头 ,后接 函数标识符名称 和 圆括号()
  • 圆括号中间 可以 放入参数
  • 函数内容以 冒号 起始,并且 缩进。
  • 最好用蛇式命名法,加下划线
    在这里插入图片描述

注意:函数 只有在调用时才会执行,通过 function_name(param) 进行调用

例题:调用九九乘法表

函数调用几次就打印几遍乘法表
def mul_table():
    for i in range(1, 10):
        for j in range(1, i + 1):
            print(f'{j}*{i}={i * j}', end="\t")
        print()

mul_table()
mul_table()
mul_table()
mul_table()

如果实现循环打印5次的话,可以在调用的时候用for循环

def mul_table():
    for i in range(1, 10):
        for j in range(1, i + 1):
            print(f'{j}*{i}={i * j}', end="\t")
        print()

for i in range(5):
    mul_table()

函数的参数

形参与实参

  • 形参 就是 函数定义中的 参数,没有实际的值,通过别人赋值后才有意义,相当于变量。
  • 实参 就是 调用函数时传入的 参数,是一个实际存在的参数。形参和实参的命名可以不一样。
    在这里插入图片描述
def test_one(b):  # 形参,函数定义时传入的
    print(b)

a = 1
test_one(a)  # 实参,函数调用时传入 输出结果为1
# 相当于 把1赋值给a,再把a赋值给b,打印b

可变类型参数与不可变类型参数

  • 不可变类型参数在函数体内对变量重新赋值,相当于重新开辟了一块内存来保存值
  • 可变类型参数在函数体内可以改变原有的值
不可变类型参数
def test_one(a):  # 形参
	#  print('inner', a, id(a))  inner 1 1438941296
    a = 10  # 整数为不可变类型,相当于重新开辟内存空间,
            # 相当于重新定义了一个变量a,只是名字一样而已,上面的a是灰色的没有被调用
    print('inner', a, id(a))  # 二者内存地址不一样

a = 1
test_one(a)  # 实参
print('outer', a, id(a))
# 输出结果inner 10 1438941584
#        outer 1 1438941296
可变数据类型
def test_one(li):  # 形参
	# print('inner', li, id(li))  inner [1, 2, 3, 4] 2026527569096
    li.append([1, 11])   # 列表为可变数据类型,在里面改和在外面是一样的,           
    print('inner', li, id(li))  # 二者内存地址一样

li = [1, 2, 3, 4]
test_one(li)  # 实参
print('outer', li, id(li))
# 输出结果inner [1, 2, 3, 4, [1, 11]] 2026527569096
#        outer [1, 2, 3, 4, [1, 11]] 2026527569096

位置参数

位置参数也就是实参与形参顺序一一对应,只跟变量的位置对应,而不论变量名,实参与形参的个数也要一致

def sum_num(a, b):
    print(f'a的位置对应num1的位置是{a}')
    print(f'b的位置对应num2的位置是{b}')
    print('a与num1的位置,b与num2的位置是一一对应的,跟参数名字无关')

num1 = int(input('请输入数字1:'))
num2 = int(input('请输入数字2:'))
sum_num(num1, num2)

关键字参数

以 形参 = 实参 形式指定,不论参数位置

def sum_num(num1, num2):
    print(f'a的位置对应num1的位置是{num1}')
    print(f'b的位置对应num2的位置是{num2}')
    print('a与num1的位置,b与num2的位置是一一对应的,跟参数名字无关')

num1 = int(input('请输入数字1:'))
num2 = int(input('请输入数字2:'))
sum_num(num1=num2, num2=num1)

以关键字传参的形式,这样的话把输入的num2传给给num1,函数里的num1得到的是函数体外num2的值,跟位置没有关系

默认值参数

形参处进行赋值,所以当调用时实参不传该参数,就默认使用形参处的值。当调用时实参传了该参数,则覆盖掉默认参数。

实参不传时,默认使用形参中指定的值
在实参中传值,会覆盖掉形参中指定的值
def test(a, b=2):
    print(a+b, b)

a = 1
test(a)  # 返回结果为 3 2,实参不传时,默认使用形参中指定的值

test(a, 10)  # 返回结果为 11 10,在实参中传值,会覆盖掉形参中指定的值

可变长度参数

*args 接收时会转为元组数据类型,可传可不传,长度不做限制,传入时实参类型不受限制,形参会打包成元组输出。
**kwargs 接收时会转为字典数据类型,可传可不传,长度不做限制,传入时实参需为键值对,形参会打包成字典输出。

# *args 可变长度参数,可传可不传,长度不限制,传入时会打包成元组
def test(*args):
    print(args)

test()  # ()空的元组
test(1, 2, 3, 5, 7,'xiaoming')  # (1, 2, 3, 5, 7, 'xiaoming')不限长度,跟数据类型无关
def test(*args,a=1):
    print(args,a)

test(1, 2, 3, 5, 7,"xiaoming") # (1, 2, 3, 5, 7, 'xiaoming') 1
test(1, 2, 3, 5, 7,a="xiaoming")  # (1, 2, 3, 5, 7) xiaoming

注意:python3.0以后,*args前面可以放任意参数,但是后面只能放关键字参数

# *args 可变长度参数,可传可不传,长度不限制,实参以键值对传入,形参会打包成字典
def test_one(**kwargs):
    print(kwargs)

test_one(a=1, b=2, c=3)  # {'a': 1, 'b': 2, 'c': 3}

元素的解包(拆包)

a,b,c = '456'
a,b,c = [4,5,6]
a,b,c = (4,5,6)
a,b,c = {4,5,6,}
print(a,b,c)  # 4 5 6
def test(tu):
    print(tu)

tu = (1, 2, 3)
test(tu) # (1,2,3)
def test(a,b,c):
    print(a,b,c)

tu = (1, 2, 3)
test(*tu)  # 1 2 3 ,如果tu前不加*会报错,因为位置参数形参与实参个数一致,并且一一对应

函数的返回值

当两个函数之间,想要互相使用到内部变量时,就可以应用到函数的返回值。
比如,要把甲房子里的电脑给乙房子用,就要先把电脑从甲房子里取出放到门口,乙房子来接收放到门口,乙房子用户再拿进去使用,相当于参数从甲中返回出来,乙去接收之后再使用。

函数的返回值定义

  • 使用 return 关键字返回内容
  • 将内容 返回到 函数调用处
  • 函数体中没有 return 语句时,函数运行结束,则默认返回 None,也被称为隐含返回值

在这里插入图片描述
小栗子:
摄氏度与华氏度关系如:摄氏度/1.8 + 32 = 华氏度
需求:
定义函数1:用于输出摄氏度
定义函数2:通过摄氏度计算得出华氏度

# 定义摄氏温度
def sheshidu(c_t):
    print(f'今天的摄氏度:{c_t}')
    # 将c_t返回到函数的调用处,如果不返回,默认值为None
    return c_t

# 定义华氏温度
def huashidu(c_t):  # 形参
   f_c = round(c_t/1.8 + 32, 2)  # 保留两位小数
   print(f'今天的华氏温度为:{f_c}')

c_t = int(input('请输入今天的温度:'))
# 函数定义完之后统一调用
t = sheshidu(c_t)
huashidu(t)  # 实参
# 也可以加个主函数 去调用
if __name__ == '__main__':
    t = sheshidu(c_t)
    huashidu(t)  # 实参

注意:函数定义完,统一在最后去调用,要将函数的返回值返回到函数调用处,才能被下个函数去调用。

函数多个返回值

  • 当执行函数体内代码时,遇到第一个 return 就将指定值返回到函数调用处,也就是执行到return这行代码,后面的都不执行了。
  • 多个返回值时,用逗号隔开,但默认为元组
    在这里插入图片描述
def test_one():
    a, b, c, = (1, 2, 3)
    # 函数中有多个return不会报错,但是只会返回第一个,后面的不再执行
    # return a
    # return b
    # return c
    return a, b, c  #相当于将abc打包成元组

res = test_one()
print(res)  # (1, 2, 3) 元组呈现
# 也可以将返回值进行拆包,逐个返回
a, b, c = test_one()
print(a, b, c)  # 1 2 3  拆包

函数的作用域

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。

"""if条件,for,while循环控制没有作用域的概念"""
if True:
    a = 5
    print(11,a)  # 5

print(22,a)  # 5
# 代码从上到下执行,先输出11 5,再输出22 5

for i in range(3):
    print("hello")  # 3个hello

print(i)  # 2
# 代码从上到下执行,先输出3个hello,再输出2

def num():
    a = 5  # 局部变量,只作用在函数体内
    print(111, a)

a = 10
print(222, a)
num()
print(333, a)
# 程序从上往下执行,先打印函数外的222 10 在打印函数体内的111 5
# 再打印函数调用后的333 10,函数体内的a属于局部变量,只针对函数有效
a = 10  # a为全局变量
def t_one():
    print(f'a = {a}')  # 没有局部变量,则取全局变量,输出为10

def t_two():
    a = 20  # 局部变量
    print(f'a = {a}')  # 有局部变量,则优先使用局部的,输出为20

t_one()
t_two()

Python 的作用域一共有4种,
分别是:

  • L(local):局部作用域,即函数中定义的变量;
  • E(enclosing):嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
  • G(global):全局变量,就是模块级别定义的变量,在函数外面定义的变量;
  • B(build-in):内建作用域,系统固定模块里面的变量,内置的只要在python环境中都能使用,比如:int(),print(),input()等
int() # build in  只要在python环境中都可以使用

a = 10  # global 全局变量

def outer():
    b = 5  # enclosing
    def inner():
        # nonlocal b # 声明b为 enclosing ,这时两个b就为同一级的,打印2个6
        # 注释掉nonlocal b 之后 内层打印6,外层打印5
        b = 6  # local
        print(11, b)

    inner()
    print(22, b)

outer()

global关键字

当我们需要在函数内部直接修改全局变量时,我们可以将函数内部的局部变量通过 global 关键字声明为全局变量

a = 10
def t_one():
    print(f'a = {a}')  # 10

def t_two():
    # a = 10  # 方法一
    global a  # 方法二
    a = a +20  # 会报错 ,因为a没有定义局部变量,系统不能区分那个a取自全局变量
                # 解决方法:1.在上方重新对a进行赋值,2.定义全局变量a
    print(f'a = {a}')  # 20

t_one()
t_two()

在这里插入图片描述

函数执行的注意点

1.代码从上到下执行
2.函数只有在被调用的时候才会执行
3.函数执行完毕,返回函数的调用处

def test():
    print('--1--')

def test1():
    print('--2--')
    test()
    print('--3--')

def test2():
    print('--4--')
    test1()
    print('--5--')

test2()

代码从上往下执行,调用test2();进入test2()内部,打印–4--,往下执行,调用 test1();进入 test1()内部,打印–2--,往下执行,调用 test();进入 test()内部,打印–1--;test()执行完毕,返回test()的调用处(test1()内部)继续执行,打印–3--;test1()执行完毕,返回test()1的调用处(test2()内部)继续执行,打印–5--,执行结束。

--4--
--2--
--1--
--3--
--5--

递归函数

阶乘第一种:(列举了共四种方法)
i = 1
sum_num = 1
while i <= 3:
    sum_num = sum_num * i  #1*1 *2 *3
    i += 1
print(f'3的阶乘3!等于{sum_num}')  #  3的阶乘3!等于6

递归的介绍

函数Func(args)直接或间接调用函数本身,则该函数称为递归函数。
小栗子:
阶乘本质:n! = 1 * 2 * 3 * … * n
使用递归函数实现阶乘

阶乘第二种:
递归函数,在函数内部调用自己
def sum_num(num):   # num为形参
    if num > 1:
        return num * sum_num(num-1)   # num-1 为实参
    else:
        return 1
#4*3 *2 *1
sm = sum_num(4)  # 24  4为实参
print(sm)

把实参4传入到形参num中,返回4*,sum_num(4-1);把实参3传入形参num,返回3*,sum_num(3-1);把实参2传入形参num,返回2*,sum_num(2-1);把实参1传入形参num,执行else语句,返回1
注意

  • 递归函数自身没有结束条件,所以需要我们自己设置结束条件,终止函数的调用。
  • 可以使用递归实现的循环都可以实现,并且递归效率很低,所以递归很少使用

内置文件中常用方法

range()
range(start,stop,step) --> range object
在这里插入图片描述
zip()用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
zip(iter[,iter2 […]]) --> zip object
在这里插入图片描述

map()
map() 会根据提供的函数对指定序列做映射。
在这里插入图片描述

filter()
filter() 用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
在这里插入图片描述

例题2题

1.返回1-10的奇数列表

# 奇数第一种:
li = []
for i in range(1, 11):
    if i % 2 == 1:
        li.append(i)
print(li)
# 奇数第二种
li = []
for i in range(1, 11, 2):
    li.append(i)
print(li)
奇数第三种
def is_odd(n):
    return n % 2 == 1  # 得到的布尔值,不管结果为True还是False都会返回,filter做了过滤的操作

print(list(filter(is_odd, range(1, 11))))
# filter函数将range(1, 11)中的每个元素传递到is_odd方法中,
# 过滤掉不符合条件的,返回为True的,构建新的filter对象,强转为列表取出元素

2.实现:阶乘,比如n!=123*…*n

阶乘第三种:
from functools import reduce # funtools是内置的模块,不需要安装,直接导入使用
def muti(x, y):
    return x * y
print(reduce(muti, range(1, 4)))   # 只能是两两传入
# 相当于先把1和2传入muti函数中,进行乘积,再将乘积的结果和3传入muti中进行乘积返回,后面依次进行

匿名函数

匿名函数介绍

函数在定义的时候要有函数名,当我们在传入函数时,有些时候,不需要重复调用该函数,直接传入匿名函数更方便,也无需担心,不用给函数命名,一次性的使用
函数名冲突,并且还可以将匿名函数赋值给一个变量,再利用变量来调用该函数。
在这里插入图片描述

# 自定义函数
def f(x):
    return x*x

print(f(3))

# 匿名函数
m = lambda x, y: x * y  # x,y是形参
print(m(2, 3))   # 2,3是实参

# 阶乘第四种:
from functools import reduce
print(reduce(lambda x, y:x*y,range(1, 7)))
# 匿名函数作为返回值
def fx(x, y):
    return lambda :x*y  # 返回的是匿名函数

f= fx(6,6)  # 返回的是lambda :x*y,赋值给f,f相当于是个函数
print(f)  # <function fx.<locals>.<lambda> at 0x000001D05F24EC80>
print(f())  # 函数只有在调用的时候才会执行,打印f()相当于又调用了返回的函数,得到结果为36

# 匿名函数作为实参
def test(a, b, func):
    res = func(a, b)
    return res

nums = test(11, 22, lambda x,y: x+y)
print(nums)  # 33

作业(4题)

1.将 lis = [4,-2,3,1] --> [1,-2,3,4]

# [4, -2, 3, 1] -- > [1, -2 ,3, 4]
# key 指定规则排序,排序之后返回原元素
li = [4, -2, 3, 1]
li.sort(key=abs)
print(li)  # [1, -2, 3, 4]

2.infors = [{‘name’:‘qian’,‘age’:28},{‘name’:‘amy’,‘age’:20},{‘name’:‘james’,‘age’:25}]以name对应的值进行排序

infors = [{'name':'qian','age':28},{'name':'amy','age':20},{'name':'james','age':25}]
# key:排序键--->获取到每个字典的name值。定义lambda函数,把infors里的每一个元素(字典)作为实参
# 传入x,返回x['name'],我们需要按照字典当中的name值去排序
infors.sort(key=lambda x:x['name'])
print(infors)

3.定义一个函数 完成用户输入的三个数字的求和以及在另一个函数求该和的平均值(用到函数传参,函数返回值

def fun_sum(sum_a, sum_b, sum_c):
    return sum_a + sum_b + sum_c

def fun_avg(sum_num, len_li):
    num_avg = sum_num/len_li
    print(f'三个数字的和为{sum_num}')
    print(f'三个数字的平均值为{num_avg}')

if __name__ == '__main__':
    ipt_li = tuple(map(float, input('请输入3个整数:').split()))
    # print(ipt_li)
    sum_num = fun_sum(*ipt_li)
    fun_avg(sum_num, len(ipt_li))

4.将列表l输出如下。l = [“jack”,(“tom”,23),“rose”,(14,55,67)]
提示:用递归实现

l = ["jack",("tom",23),"rose",(14,55,67)]
# 如果遇到的是"jack","rose" 就直接输出
# 如果遇到的是(,),就去遍历
# 方法一:
for item in l:
    if type(item) == tuple:
        for i in item:
            print(i)
    else:
        print(item)

# 方法二:
for item in l:
    # isinstance(x, A_tuple)判断x是否是A_tuple的类型
    if isinstance(item, tuple):
        for i in item:
            print(i)
    else:
        print(item)

# # 方法三:
def get_ele(l):
    for item in l:
        if isinstance(item, tuple):
            get_ele(item)
        else:
            print(item)
get_ele(l)

# 方法四:
def get_ele(l):
    # 判断l是整数或者是字符串
    if isinstance(l, (str, int)):
        print(l)
    else:
        for item in l:
            get_ele(item)
get_ele(l)

举报

相关推荐

0 条评论