day10-Function application

01 recode

1. 函数的声明(声明函数的时候不会执行函数体)

def 函数名(参数列表):
    函数的说明文档 ---> 放在引号注释里,注释说明函数功能
    函数体

参数列表中的阐述可以进行参数类型说明(只是进行说明,没有强制限制类型,但一般不要违反)可以通过 参数名: 类型名 来指定参数的类型,也可以通过设置默认值来说明参数的类型

def 函数名(参数1: int, 参数2=[])
  • 说明类型的好处:

    a. 传什么类型参数一目了然
    b. 实现函数体时有相应的代码提示

  • return 也可以进行说明

def 函数名(参数1: int, 参数2=[]) ->返回值类型:

2. 函数的调用

  • 格式:
    函数名(实参列表)
  • 调用过程:
    第一步:回到函数声明的位置
    第二步:用实参给形参赋值 ---> 传参(保证每个参数都要有值)
    第三步:执行函数体
    第四步:确定返回值 ---> 将函数调动表达式设置为返回值
    第五步:回到函数调用的位置,接着往后执行

3. 函数的参数

  • 分类
    位置参数
    关键字参数
    参数的默认值 ---> 有默认值的参数要放在没有默认值的参数后面
    不定长参数 ---> 在参数前面加 * 下面有补充
def func1(a: int, b=[]):
    """
    把参数a 添加到列表b中
    :param a:
    :param b:
    :return:
    """
    b.append(a)
    return b    


print(func1(1, [1, 2, 3]))  #[1, 2, 3, 1]


  • 补充:不定长参数(面试题)
  • 说说*args, **kwargs之间的区别
    • args 就是参数名前加一颗, 将位置参数作为元组的元素,参数就是一个元组

    • kwargs 就是参数名前加两颗,必须以关键字的方式传参,然后将关键字参数转换为字典

    • 注意:经常将 *args 和 **kwargs放在一起组合使用,但是使用的时候,两颗星的要放在后面传参数的时候,关键字参数也要放在位置参数后面


def func2(*args, **kwargs):
    print(args, kwargs, sep = "\n")


func2(1, 2, 3, 4, {"b": 1}, a = 12)   # (1, 2, 3, 4, {"b": 1}), {"a": 12}

func2(1, 2, 3)                      # (1, 2, 3) {}
func2(a = 1, b = 2, c = 3)          # () {"a": 1, "b": 2, "c": 3}

4. 返回值

python中所有的函数都有返回值,默认的返回值是None,如果遇到return,函数的返回值就是return后面的值

返回值就是函数调用表达式的值
调用函数的目的:a. 执行函数体 b. 获取返回值

函数调用表达式: fun_x(实参)
  • return的作用: a. 返回返回值 b. 结束函数(函数中遇到return就结束函数)

02 匿名函数

    1. 普通函数:
def 函数名(参数列表):
    函数体
    1. 匿名函数:

函数名(变量名) = lambda 参数列表:返回值

  • 说明:
    a. 函数名 ---> 变量名
    b. lambda ---> 声明匿名函数的关键字
    c. 参数列表 ---> 由多个参数组成,至少有一个
    d. 返回值 ---> 相当于只有一个return语句的函数体

匿名函数的调用和普通函数一样,支持位置参数, 关键字参数, 参数也可以设置默认值, 支持不定参数

  • 特点:
    直接将函数的声明作为一个值存到一个变量
    将函数声明赋给一个变量
# 求两数之和


sum_num = lambda x, y: x + y

print(sum_num(10, 20))      # 30


# 求1+2+……n的和
sum_nums = lambda n: sum(range(n+1))

print(sum_nums(100))        # 5050

sum1 = lambda *num:sum(num)
print(sum1(1, 2, 3))        # 6


# 练习:读程序
funcs = []
for item in range(1, 5):    # 执行完循环 funcs = [lambda x: x * item, lambda x: x * item, lambda x: x * item, lambda x: x * item]
    funcs.append(lambda x: x * item)    # 循环结束后item = 4

print(funcs[0](2))      # 8
print(funcs[1](2))      # 8

03 变量的作用域

    1. 变量的作用域
      变量的作用域指的是变量能够使用的范围
    1. 全局变量
      全局变量:声明在函数和类的外面的变量都是全局变量;
      作用域:作用域是从声明开始到整个Py文件结束都可以使用
  • 全局变量 a 、 b 、 x 都是全局变量,只有涉及函数和类里面的变量才是局部的
a = 10
print("=====")
for x in range(2):
    b = 5
    print(a)        # 10 10

if True:
    print(a)        # 10

print(a)        # 10
print("=====")
    1. 局部变量
      声明在函数和类中的变量都是局部变量,声明在函数的局部变量,作用域从声明开始到整个函数结束,只能在函数局部使用
def func1():
    aa = 100
    bb = 200

# print(aa, bb)     报错,aa和bb没有被定义
    1. global关键字
      只能在函数里用:在函数中声明一个全局变量
name = "abc"


def func2():
    global name    # 说明当前函数中使用的name是全局变量的name
    print(name)     
    name = "aaa"
    print(name)     


func2()     # "abc" "aaa"
print(name)     # "aaa"
    1. nonlocal 关键字
def func5():
    a1 = 500
    # nonlocal a1       # 就算声明a1非局部的也不能在函数外使用,依旧是局限于函数内部的
    # global a1         # 就算在函数内声明a1为全局变量,但是只要函数外没有a1被声明,a1也是函数内的
    def func6():
        nonlocal a1     # 让a1不仅仅作用域在func6(),也可以作用于上一级的函数
        print(a1)
        a1 = 600
        print(a1)
    func6()
    print(a1)

func5()     # 500 600 600

04 函数作为变量

声明函数就是声明一个类型是function的变量,函数名是指就是变量名

def func1():
    print("========")


print(type(func1))      # Class 'function'
# print(func1)          # 打印出 function func1 at oxoo6155d0  打印出func1的被存于oxoo6155d0
    1. 变量能给其他变量赋值
a = 10      # 普通变量赋值
b = a
print(b * 10)       # 100


list1 = [1, 2]
list2 = list1[:]
print(list2*2)      # [1, 2, 1, 2]

# 函数给变量赋值
def func2():
    print("我是函数")


x = func2       # 将func2 赋值给x
x()     # "我是函数"
print(type(x))      # class "function"



func3 = lambda x: print(x)      # 将func3赋值给y
y = func3
y(2)        # 2
    1. 函数作为列表的元素
   a = 10
   list4 = [1, a]
   print(list4, list4[1] + 100)     # [1, 10] 110


def func10():
    print("我是函数")
    return 10

print("----------")
list5 = [1, func10, func10()]       # list5[2] 首先会调用函数打印,之后将返回值存在列表中
print(list5)        # [1, func10, 10]


print("========================")
print(list5[1]())       # 调用函数执行打印 "我是函数",然后打印出函数的返回值 10
    1. 将函数作为参数
print("==--==--==--==--==--==--")
a = 10
def func_a(n):      # 往函数中传普通变量
    print(n)


func_a(a)       # 10


# 给函数传函数
def func_b(n):
    # n = func_c
    n()     # 执行 func_c(),打印出 "hello python"


def func_c():
    print("hello python")

func_b(func_c)      # "hello python"
  • 应用:sort的使用

列表.sort(key=None, reverse=False)

使用sort时,可以给key赋一个函数变量来规定函数用什么标准来排序,这儿的函数变量要求要有一个参数和一个返回值,参数代表列表中的元素,返回值代表按照那个标准排序

list1 = [1, 2, 55, 33]      # 列表中可以直接排序
list1.sort()
print(list1)                # [1, 2, 33, 55]


list2 = [{"name": "张三", "age": 20, "grades": 90},       # 列表中有多个元素用key排序
         {"name": "李四", "age": 18, "grades": 99},
         {"name": "王二麻子", "age": 32, "grades": 77}]

def key_age(item):
    return item["age"]      # [{"name": "李四", "age": 18, "grades": 99}, {"name": "张三", "age": 20, "grades": 90}, {"name": "王二麻子", "age": 32, "grades": 77}]

# list2.sort(key=lambda item: item["age"])
list2.sort(key=key_age)   #根据年龄排序
print(list2)


# 让list3以第二个元素倒序排列
# method one
list3 = [(10, 2), ("c", 23), (33, 44)]
def key_2(item):
    return item[1]      

list3.sort(key=key_2, reverse=True)
print(list3)        # # [(33, 44), (23, "c"), (10, 2)]

# method two
list3 = [(10, 2), ("c", 23), (33, 44)]
list3.sort(key=lambda item: item[1], reverse=True)
print(list3)
    1. 将函数作为返回值

    根据运算符,返回运算符对应的功能 功能对应的就是函数

def operation(operator: str):
    if operator == "+":
        def func1(*args, **kwargs):     # func1 相加功能
            """
            求和功能
            :param args:   (1, 2)
            :param kwargs:  {"a": 3, "b", 4}
            :return:
            """
            sum1 = 0
            for item in args:
                sum1 += item
            for keys in kwargs:
                sum1 += kwargs[keys]
            return sum1
        return func1
    
    elif operator == "*":
        def func2(*args, **kwargs):     # func2  相乘功能
            """
            xiang功能
            :param args:   (1, 2)
            :param kwargs:  {"a": 3, "b", 4}
            :return:
            """
            sum1 = 1
            for item in args:
                sum1 *= item
            for keys in kwargs:
                sum1 *= kwargs[keys]
            return sum1
        return func2


f1 = operation("+")     # f1 = func1,f1就是具有两个不定长参数的有求和功能的函数
re = f1(1, 2, a=3, b=4)
print(re)       # 10
# print(operation("+")(1, 2, a=3, b=4))


f2 = operation("*")     # f2 =func2
re = f2(1, 2, a=3, b=4)
print(re)       # 24
# print(operation("*")(1, 2, a=3, b=4))

05 函数的调用

    1. 补充: python中的函数可以有多个返回值

求多个数的和以及平均值

def sum_num(*nums):
    sum1 = sum(nums)
    average = sum1 / len(nums)
    return sum1, average        # 同时返回和、平均值


a, b = sum_num(2, 35, 6, 33, 76)        
num = sum_num(2, 35, 6, 33, 76) # 返回的num为一个元组

print(a, b)     # 152 30.4
print(num[0], num[1], num)      # 152 30.4 (152, 30.4)
    1. 函数的调用过程是一个压栈的过程

    每次调用函数的时候,系统都会在内存中(栈)开辟空间来存储函数执行过程中产生的数据(形参、声明的变量),当函数调用完成后,这块内存会自动销毁栈内存特点:申请和释放由系统完成

06 递归函数了解一哈

    1. 什么是递归函数(会导致内存在一段时间猛增猛减,消耗cpu资源)递归函数:函数中调用函数本身,这样的函数就是递归函数(自己调用自己)

循环能做的事情,递归都可以做,但是实际上循环能解决的事情,绝对不选递归

def func1():
    print("===")
    func1()

# func1()       达到最大递归次数,内存不够 maximum recursion depth exceeded while calling a Python object
    1. 怎么写递归函数

    第一步 确定临界值(循环结束的条件),让函数结束
    第二步 找关系,假设函数功能已经实现,找f(n)和f(n-1)的关系
    第三步 根据关系,用f(n-1)实现f(n)的功能

写递归函数,实现1+2+3+...n

def ey_sum(n):
    # 1. 找临界值
    if n == 1:
        return 1

    # 2. 找关系
    # ey_sum(n) = 1+2+3+……n
    # ey_sum(n-1) = 1+2+3+……n-1
    # ey_sum(n) = ey_sum(n-1) + n


    # 3. 用f(n-1)实现f(n)功能
    return ey_sum(n-1) + n

print(ey_sum(5))        # 15
  • 调用过程:
ey_sum(5)   return  ey_sum(4) + 5   1 + 2 + 3 + 4 + 5
ey_sum(4)   return  ey_sum(3) + 4   1 + 2 + 3 + 4
ey_sum(3)   return  ey_sum(2) + 3   1 + 2 + 3
ey_sum(2)   return  ey_sum(1) + 2   1 + 2 
ey_sum(1)   return  1 

用递归实现以下功能

n = 3  
打印
***
**
*


def ey_star(n):
    if n == 1:
        print("*")
        return
    
    print("*"*n)
    ey_star(n - 1)


ey_star(5)      # *****
                # ****
                # ***
"""             # **
n = 3           # *
打印
*
**
***
"""
def ey_print(n):
    if n == 1:
        print("*")
        return
    ey_print(n - 1)
    print(n*"*")

ey_print(5)     # *
                # **
                # ***
                # ****
                # *****

总结:递归能不用就不用

你可能感兴趣的:(day10-Function application)