函数

函数简介

  • 函数也是一个对象
  • 函数用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次调用
语法
def 函数名([形参1,形参2,形参3....]):
    代码块
  • 注意:
    函数名必须符合标识符的规范(可以包含字母、数字、下划线但是不能以数字开头)
    print是函数对象 print()是调用函数

函数的参数

1. 形参和实参

  • 形参(形式参数) 定义形参就相当于在函数内部声明了变量,但是并不是赋值
  • 实参(实际参数)指定了形参,那么在调用函数时必须传递实参,实参将会赋值给对应的形参,简单来说有几个形参就要有几个实参
def fun(a,b): # 这个参数叫做形参 也叫形式上的参数
    print(a,b)
fun(1,2) # 实参 实际参数 当你调用的时候传递实际参数

  • 定义形参时,可以为形参指定默认值。指定了默认值以后,如果用户传递了参数则默认值不会生效。如- - 果用户没有传递,则默认值就会生效
def fun(a,b=2,c=3): # c=3 给形参指定默认值,当没有传递实参的时候,使用默认值,当传递了参数,使用传递进来的参数
    print(a,b,c)
fun(3,4)

  • 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参
  • 关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递
  • 混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面去
def fun(a, c, b):
    print(a)
    print(b)
    print(c)
fun(1, 3, b=2)
# 位置传参和关键字传参混合使用, 位置传参必须放到关键字传参的前面

2. 函数的传递方式

  • 定义形参时,可以为形参指定默认值。指定了默认值以后,如果用户传递了参数则默认值不会生效。如果用户没有传递,则默认值就会生效
  • 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参
  • 关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递
  • 混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面去
def fun1(a,b=3,c=6): # b和c两个形参指定了默认值,当没有实参传入的时候,使用默认值,当有实参传入时使用实参
    print(a,b,c)
fun1(1,4)

def fun1(a,b=3,c=6): 
    print(a,b,c)
fun1(1,b=4) # 位置传参要放在关键字传参前

3. 不定长参数

  • 定义函数时,可以在形参前面加一个*,这样这个形参可以获取到所有的实参,它会将所有的实参保存到一个元组中
  • 带*号的形参只能有一个,可以和其他参数配合使用
  • *形参只能接受位置参数,不能接受关键字参数
def fun(c,*a,d): # 位置传参的不定长参数:只能存在一个参数有*号,可以和其他的传参方式一起配合使用,位置参数不能放在不定长参数的后面,不定长参数*a要放在关键字传参的前面
    print(a)
    r=0
    for i in a:
        r+=i
    print(r)
fun(1,3,4,d=2)
  • **形参可以接收其他的关键字参数,它会将这些参数统一保存到字典当中。字典的key就是参数的名字,字典的value就是参数的值
  • **形参只有一个,并且必须写在所有参数的后面
def fun1(*g,**e): #(万能传参) #关键字传参的不定长参数:位置传参必须放到不定长参数的前面,关键字传参要放在不定长参数之前
    print(g)
    print(e)
fun1(1,2,a=1,b=2,c=3,d=4,h=1)

4. 参数的解包

  • 传递实参时,也可以在序列类型的参数前添加星号,这样它会自动的将序列中元素依次作为参数传递
  • 要求序列中的元素的个数必须和形参的个数一致
def fun1(a,b,c):
    print(a,b,c)
dict1={'a':1,'b':2,'c':3}
fun1(**dict1)

函数的返回值

  • 返回值就是函数执行以后返回的结果
  • 通过return来指定函数的返回值
  • return后面可以跟任意对象,返回值甚至可以是一个函数
# 创建函数是做一个什么事情: 实现一些代码,完成一个功能的开发,在函数里的东西,你要想拿到函数外面去用,那必须要返回出来,也就是说必须由return返回出来
def fun(*a): # 函数内的变量执行结果,想要直接到函数外面去使用,是不行的
    r = 0
    for i in a:
        r +=i
    print(r)
    return a
res=fun(1+2,3) # 函数的调用fun() fun(1+2,3)等于函数的返回值(即等于a) 也就是说等于return返回的值
print(res)
# 1.函数参数的传递
# 2.函数的调用
# 3.函数的返回值
# 4.函数的调用等于什么

文档字符串

  • help()是Python中内置函数,通过help()函数可以查询Python中函数的用法
  • 在定义函数时,可以在函数内部编写文档字符串,文档字符串就是对函数的说明
1.保留文本的格式
2.作为一个多行注释
'''

# 文档字符串,就是对函数以及类进行说明作用及参数返回的一个文档说明
def fun(a,b):
    """

    :param a:
    :param b:
    :return:
    """
help(print)
help(input)
help(fun)

函数的作用域

  • 作用域(scope)
  • 作用域指的是变量生效的区域
  • 在Python中一共有两种作用域
    • 全局作用域
    • 全局作用域在程序执行时创建,在程序执行结束时销毁
    • 所有函数以外的区域都是全局作用域
    • 在全局作用域中定义的变量,都是全局变量,全局变量可以在程序的任意位置进行访问
    • 函数作用域
    • 函数作用域在函数调用时创建,在调用结束时销毁
    • 函数每调用一次就会产生一个新的函数作用域
    • 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问
a=1
def fun():
    # 使局部作用域变为全局作用域的办法
    global a # 声明此处的变量a是全局变量
    a=10 #a的重新赋值
    print(a)
    def fun1():
        print(a)
    fun1()
fun()
print(a)

高阶函数

  • 接收函数作为参数,或者将函数作为返回值返回的函数就是高阶函数
def fun2(i):
    if i %2==0:
        return True


def fun(fun2):
    list1 = []
    for i in range(101):
        if fun2(i):
            list1.append(i)
    return list1
res=fun(fun2)
print(res)

递归函数

  • 递归是解决问题的一种方式,它的整体思想,是将一个大问题分解为一个个的小问题,直到问题无法分解时,在去解决问题
  • 递归式函数有2个条件
    • 基线条件 问题可以被分解为最小问题,当满足基线条件时,递归就不执行了
    • 递归条件 可以将问题继续分解的条件
n=1
for i in range(1,11):
    n=n*i
print(n)


def fun(n):
    r=1
    for i in range(1,n+1):
        r=r*i
    return r
print(fun(10))

# 使用递归函数
def fun(m,n):
    if n==1:
        return m
    return m*fun(m,n-1)
print(fun(10,5))

闭包

  • 将函数作为返回值也是高阶函数我们也称为闭包
  • 闭包的好处
    • 通过闭包可以创建一些只有当前函数能访问的变量
    • 可以将一些私有数据藏到闭包中
  • 行成闭包的条件
    • 函数嵌套
    • 将内部函数作为返回值返回
    • 内部函数必须要使用到外部函数的变量
# def fun_out(num1):
#     def fun_inner(num2):
#         res=num1+num2
#         return res
#     return fun_inner
# f=fun_out(1)
# print(f(2))

def fun_out(num1):

    # 定义一个内部函数
    def fun_inner(num2):
        # global num1
        nonlocal num1  # 告诉解释器,这里使用的不是本地的num1, 是外部变量的num1
        num1 = 10
        res = num1 + num2
        # print(res)
        return res

    print(num1)
    fun_inner(1)
    print(num1)
    return fun_inner
f = fun_out(1)
print(f(2))

匿名函数

匿名函数的特点

  • 使用lambda关键字创建匿名函数。
  • 所谓匿名函数,就是没有名字的函数。
  • 匿名函数冒号后面的表达式有且只能有一个,注意:是表达式,而不是语句。
  • 匿名函数自带return,而return的结果就是表达式的计算后的结果。

匿名函数的语法

  • 语法: lambda 参数:表达式
print((lambda a, b: a + b)(1, 2))

装饰器

装饰器的引入

  • 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
    • 如果修改的函数多,修改起来会比较麻烦
    • 不方便后期的维护
    • 这样做会违反开闭原则(ocp)
      • 程序的设计,要求开发对程序的扩展,要关闭对程序的修改

装饰器的使用

  • 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
  • 在开发中,我们都是通过装饰器来扩展函数的功能的
# 装饰器是一个特殊的闭包函数
def old_fun(fn):
    def new_fun(*args,**kwargs):
        print('函数开始执行')
        print(fn(*args,**kwargs))
        print('函数执行结束')
    return new_fun

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

r=old_fun(fun)
r(1,2)

def old_fun(fn):
    def new_fun(*args,**kwargs):
        print('函数开始执行')
        print(fn(*args,**kwargs))
        print('函数执行结束')
    return new_fun
@old_fun
def fun(a,b):
    return a+b
fun(1,2)

Homework

  • 1.打印名片程序:输入姓名,电话号码,性别,最后打印出来名片
    • 控制姓名长度为6-20
    • 电话号码长度11
    • 性别只能允许输入男或女
    • 每一样信息不允许为空
while True:
    name=input('请输入姓名')
    if len(name) <6 or len(name)>20:
        print('输入的姓名不对,请重新输入')
        continue
    tel= input('请输入电话号码')
    if len(tel) !=11:
        print('你输入的电话号码不对,请重新输入')
        continue
    gender=input('请输入性别,男或女')
    if gender!='男' and gender!='女':
        print('性别不对请重新输入')
        continue
    break
def Card(name,tel,gender):
    print('''
    **************************
    姓名: {}
    手机号: {}
    性别: {}
    --------------------------
    '''.format(name,tel,gender))
Card(name,tel,gender)
  • 2.使用函数求前20个斐波那契数列斐波那契数列:1,1,2,3,5,8,13,21…即: 起始两项均为1,此后的项分别为前两项之和
def feibo(num):
    a,b=1,1
    list1=[]
    for i in range(num):
        if i<0:
            list1.append(a)
        elif i>0:
            a,b=b,a+b
            list1.append(a)
    print(list1)
feibo(20)
  • 3.用函数实现一个判断用户输入的年份是否是闰年的程序
    • 能被400整除的年份
    • 能被4整除,但是不能被100整除的年份
    • 以上2种方法满足一种即为闰年
def main():
   year=int(input('请输入一个年份'))
   if year % 400 ==0:
       print(year,'是一个闰年')
   elif year % 4 ==0 and year % 100 !=0:
       print(year,'是一个闰年')
   else:
       print(year,'不是一个闰年')
main()
  • 4.猴子吃桃问题(递归):
    猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了,求第一天共摘了多少桃子?
# 思路分析:
# 总共有f(1)个桃子,每天吃一半后再吃一个,第十天剩余一个
# 第一天桃子数f(1),第二天f(2)=f(1)/2-1,第三天f(3)=f(2)/2-1.......f(n+1)=f(n)/2-1,当n=10时 f(10)=f(9)/2-1=1
#则可以推导出f(n)=(f(n+1)+1)/2,使用递归函数求出总数

def fun(n):
    if n<1 or n>10:
        print('天数必须为1至10请重新输入')
    else:
        if n==10:
            return 1
        return (fun(n+1)+1)*2
res=fun(2)
print(res)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值