Python 基础的核心——函数

Python 基础的核心——函数

设计函数最为重要的原则: 单一职责原则(一个函数只做好一件事情)————> 高度内聚低耦合
high cohesion low coupling 一个函数做一件事

函数的定义

在Python中可以使用def关键字来定义函数,和变量一样每个函数也应该有一个漂亮的名字,命名规则跟变量的命名规则是一致的。

def后还有(): 括号里可以填参数 ,参数我们后面讲。

函数 —> y = f(x) / z = f(x, y) / … —> 相对独立且会被重复使用的功能(代码),将来想使用这些功能的时候,不需要再复制粘贴代码,而是直接通过调用函数来做到。

自变量(argument) —> 参数(parameter)
因变量 —> 返回值(return value)

参数,相当于输入的自变量

return 返回的是因变量

#定义函数:def是定义函数的关键字、ptp是函数名,data是参数(自变量)
def ptp(data):
    return max(data) - min(data)
# return 返回的就是 极差

在这里插入图片描述

还可以对重复代码提取出来进行重构名

在这里插入图片描述

函数的注释

好的注释具有好的可读性,写好注释不做猪队友。

  • 1、在第二行打上三给双引号回车后就成下面样子

  • 2、然后对函数的作用进行说明

  • 3、再对参数,和返回值进行说明

  • 4、参数冒号后面是参数的类型,括号外面的是返回值的类型。

def ptp(data :list) -> int:  
    """
    求极差
    :param data: 输入一个列表数据
    :return: 返回极差
    """
    return a + b

函数的参数

参数是函数中非常重要的结构

参数主要有

  • 位置参数 : 参数在 * 号前对号入座即可 ,不用带参数名

  • 可变参数 : 传入0个或任意多个参数

  • 关键字参数 : 带参数名传入多个参数

    当函数的参数个数无法确定时,我们可以利用下面两个关键字来接收参数

*args 可以接收零个或多个位置参数,将所有位置参数打包为一个元组。
**kwargs 可以接收零个或多个关键字参数 ,将所有的关键字参数打包为一个字典。

def add(*args,**kwargs):
    """
    计算输入的值的和
    :param args:
    :param kwargs: 
    :return:   输入值求和
    """
    total = 0
    for arg in args:
        if type(arg) in (int,float):
            total += arg
    for value in kwargs.values():      
        if type(value) in (int,float):  #避免字符串带来的报错
            total += value
    return  total
#由于args 和 kewargs 是位置参数与关键字参数  
#如果不带参数名输入,其实就是由aegs接收的
#如果带得有参数名则是由kwargs参数接受的

#如果带有参数名 却 只用 args传入则会报错
#反之不带参数名 只用 kewargs 传入也会报错
print(add())      #0
print(add(1))     #1
print(add(1,b=2)) #3
print(add(1,b='2',c=3))  #4
print(add(1,b=2,c='hello',d=4))   #7

还有就是调用的时候未指定参数的值那么输出的结果是默认的

def ptp(a=3,b=2):
    """
    求差
    :param a: 输入一个数据
    :param b
    :return: 返回差
    """
    return a-b

print(ptp())   #参数是默认的  结果为3-2=1
print(ptp(5,2))  #指定参数替代默认值 且对号入座 5-2=3
print(ptp(2,5))   #-3

全局变量和局部变量

  • Python程序中搜索一个变量是按照 LEGB 顺序进行搜索的

    Local(局部作用域) —> Embeded(嵌套作用域) —> Global(全局作用域)

    global —> 声明使用全局变量或者定义一个局部变量将其放到全局作用域
    nonlocal —> 声明使用嵌套作用域的变量(不使用局部变量)

"""
全局变量和局部变量

全局变量(没有写在任何函数里面的变量)
局部变量(定义在函数内部的变量)

---> Built-in(内置作用域) ---> NameError: name ... not defined

global ---> 声明使用全局变量或者定义一个局部变量将其放到全局作用域
nonlocal ---> 声明使用嵌套作用域的变量(不使用局部变量)

"""
x = 100


def foo():
    # 如果我不想在函数foo中定义局部变量x,想直接使用全局变量x,应该怎么做???
    #global x
    x = 200

    def bar():
        # 如果我不想在函数bar中定义局部变量x,想直接使用嵌套作用域中的x,应该怎么做???
        #nonlocal x
        x = 300
        print(x)  #300

    bar()
    print(x)#200


foo()
print(x)   #100

#自己可以改变每个变量x的值 观察其输出情况

函数的高阶运用与lambda函数

在python中函数是一等函数(一等公民):
1.函数可以作为函数的参数,
2.函数可以作为函数的返回值
3.函数刻意赋值给变量

如果把函数作为函数的参数或者返回值,这种玩法称之为高阶函数
通常使用高阶函数可以实现对原有函数的解耦合操作。
运算 - operate,运算符 - operator

Lambda函数 —> 没有名字而且一句话就能写完的函数,唯一的表达式就是函数的返回值

"""
example03 - 编写实现对列表元素进行冒泡排序的函数

设计函数的时候,一定要注意函数的无副作用性(调用函数不影响调用者)

Date: 2021/8/4
"""


def bubble_sort(items, ascending=True, gt=lambda x, y: x > y):
    """冒泡排序

    :param items: 待排序的列表
    :param ascending: 是否使用升序
    :param gt: 比较两个元素大小的函数  可以降低代码耦合度
    :return: 排序后的列表
    """
    items = items[:]
    for i in range(1, len(items)):
        swapped = False
        for j in range(0, len(items) - i):
            if gt(items[j], items[j + 1]):   #原代码式items[j] > items[j + 1]  现在把它改变
                items[j], items[j + 1] = items[j + 1], items[j]
                swapped = True
        if not swapped:
            break
    if not ascending:
        items = items[::-1]
    return items


if __name__ == '__main__':  #导入此模块的时候不会执行下列操作
    # nums = [35, 96, 12, 78, 56, 64, 39, 80]
    # print(bubble_sort(nums, ascending=False))
    # print(nums)
    
    #可以通过改变lambda 后面的关键字来替代代码中的表达式
    words = ['apple', 'watermelon', 'hello', 'zoo', 'internationalization']
    print(bubble_sort(words, gt=lambda x, y: len(x) > len(y), ascending=False))

函数的递归

函数可以自己调用自己

函数如果直接或间接的调用了自身,这种调用称为递归调用。

不管函数是调用别的函数,还是调用自身,一定要做到快速收敛。
在比较有限的调用次数内能够结束,而不是无限制的调用函数。

如果一个函数(通常指递归调用的函数)不能够快速收敛,那么就很有可能产生下面的错误
RecursionError: maximum recursion depth exceeded
最终导致程序的崩溃。

"""
阶乘的定义:
~ n! = n * (n - 1) * (n - 2) * ... * 2 * 1
~ n! = n * (n - 1)!

递归函数的两个要点:
1. 递归公式(第n次跟第n-1次的关系)
2. 收敛条件(什么时候停止递归调用)

Author:
Date: 2021/8/4
"""


def fac(num: int) -> int:
    """求阶乘(递归写法)"""
    if num == 0:
        return 1
    return num * fac(num - 1)


if __name__ == '__main__':
    # return 5 * fac(4)
    # return 4 * fac(3)
    # return 3 * fac(2)
    # return 2 * fac(1)
    # return 1 * fac(0)
    # return 1
    print(fac(5))

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

在这里插入图片描述

常用代码模块,快捷键设置

mac系统

在这里插入图片描述

win

在这里插入图片描述

跨文件建包

在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值