Python基础语法详解(进阶篇)

Python基础语法(3)

函数

在我们有了之前的语法基础之后,现在我们来认识一下Python中的函数
在数学中,我们有各种的函数,而编程语言中的函数和数学中的函数不太一样


什么是函数

简单来说,在编程语言中的函数,就是一段封装好的,可以反复使用的代码

比如我们需要实现一个两个数相加的功能,这时候,我们有几组数据,那可能需要写几次相加的代码,但是我们如果写好了一个相加函数,那么每次我们只需要在需要加的时候调用这个函数就好了

#计算下面几组数据的和
# 12 56
# 33 45
# 42 67
#方法一:一个个写

a = 12
b = 56
the_sum = a + b
print(the_sum)

a = 33
b = 45
the_sum = a + b
print(the_sum)

a = 42
b = 67
the_sum = a + b
print(the_sum)

# 方法二:函数
def the_sum(a,b)
    return a+b
print(the_sum(12,56))
print(the_sum(33,45))
print(the_sum(42,67))

我们可以对比一下,使用函数和不使用函数,无论是在代码量和后期的代码管理上来看,都是前者都是更好的


函数的定义和调用

定义

那么我们该如何定义一个函数呢

# 函数定义的语法规则
def 函数名(形参列表):
    函数体
    return 返回值

首先,我们需要用def来声明一下,接下来我们定义的是一个函数,如何函数名(命名规则和变量名的规则一样)

之后括号里面就是我们的参数,可以是一个或者多个,后面用冒号(英文)表示结束

下面用一个缩进表示函数体,也就是这函数内部实现功能的代码

最后某些函数可能需要有返回值,也有函数只要实现功能就好了不需要返回值,所以这个return按需取舍

调用

那我们定义好了一个函数,怎么来调用它呢

# 调用函数
#对于没有返回值的函数
函数名(实参列表)
#对于有返回值的函数,我们可以用一个变量来接受这个返回值
变量=函数名(实参列表)
  • 注意,函数调用都是写在函数定义之后的
  • 在代码执行的过程中,我们先不会执行函数部分的代码,只要在调用函数的时候,才会去执行函数部分的代码
  • 这里和c++/java不同的是,Python中的函数参数,没有严格的类型匹配要求(只要函数体内的操作支持接收的类型就行)


    函数的实参,形参,返回值

    实参和形参

    在我们调用一个函数的时候,我们在()中所写的参数就是实参

    顾名思义也就是我们用函数解决问题的时候,实际需要具体值

    我们在定义函数的时候()里的参数,我们把它们叫作形式参数

    也就是配合我们实现功能的,具体是什么值,需要我们赋予它

    # 例如下面我们来实现一个加法函数
    
    def add(x,y):# 这里的x,y就是形式参数
        return x,y
    
    a=10
    b=20
    print(add(a,b))#这里的a,b就是实际参数
    
    

    这里有几点我们需要注意一下

    ①实参和形参本质上不是同一个东西,之前我们说过,变量的创建,实际上是在内存中开辟了一块空间

    而形参其实是再开辟了一块空间,然后将实参的值,拷贝了一份过来,也就是说对于形参进行一些改变操作,对于实参是不会有影响的

    #我们可以写一下交换函数
    #再函数里,交换形参的值,看看实参的值是否交换
    def change(x,y):
        z=x
        x=y
        y=x
    a=1
    b=2
    change(a,b)
    print(a,b)
    


    a,b的值并没有交换

    ②形参和实参的变量名可以用一样的

    ③我们在定义函数的时候,可以给形参一个默认值,我们会将有默认值的参数写在后面

     def add(x,y,debug=False):
            if debug:
                print(x,y)
            print(x+y)
    a=10
    b=20
    add(a,b)#可以不传debug
    print("----------")
    add(a,b,True)#也可以传debug,用来实现更多需求
    

    ④我们在进行传参的时候,默认是按位置传递的,也就是顺序传递,当然我们也可以在实参前加上关键字,就可以不按位置传递

    def add(x,y):
        print(x,y)
    add(y=10,x=20)#这样也可以实现参数的传递
    

    顺序传递和关键字传递可以混用,但是关键字传递要写在顺序传递之后哦

    返回值

    对于返回值,我们来讲几个特别的用法

    ①多元赋值

    我们有时候可能需要返回两个值,例如坐标,这时候,可以用多元赋值的方法来接收返回值

    def add(x,y):
        return x,y
    a,b = add(10.20)
    #如果我们只想接收其中一个,可以用_来进行占位
    _,c = add(12.23)
    

    ②链式调用

    链式调用是用第一个函数的返回值,作为第二个函数的参数,本质上是一种嵌套

    #我们最常见的打印一个求和函数的值就是链式调用
    def add(x,y):
    	return x+y
    print(add(10,20))#用求和函数返回的和,来作为打印函数要打印的对象
    

    这里说明一下,因为每调用一个函数,就需要在内存中开辟出它的函数栈帧(空间),所以我们嵌套的层数不能太多哦


    函数变量的作用域

    我们在函数内部创建出来的变量,只能作用于这个函数内部,出了函数,它的空间就会释放,也就不存在了

    def add(x,y):
        z=x+y
    add(10,20)
    print(z)    #像这样就会报错
    

    如果我们想让函数内部创建的变量在外面也能被使用,我们可以用global来声明一下,这样z就成为全局变量了

    def add(x,y):
        global z
        z = x+y
    add(10,20)
    print(z)    #像这样就不会报错
    

  • if else for while里面创建的变量是全局的,Python中只有函数和类中创建的是局部变量
  • 同样的,如果在函数内部创建了一个和外面同名的变量,那么函数里面使用的,还是函数内部创建的变量

    def test():
        x=10
        print(f"内{x}")
    x=20
    test()
    print(f"外{x}")
    

    当然,我们可以直接在函数中使用已经创建好的全局变量

    def test():
        print(x)
    x=10
    

    函数递归

    递归,就是函数自己调用自己,通常我们需要解决一个大问题的时候,可以把他转化成一些子问题,这时候可能就需要递归

    我们用一个求阶乘的问题来举例

    # 我们求一个n的阶乘,这时候,就可以把他转换为先求n-1的阶乘,于此类推的子问题
    def jiecheng(n):
        if n==1:
            return 1
        return n*jiecheng(n-1)
    print(jiecheng(5))
    

    对于递归,我们有几个需要注意的地方

    ①要有一个递出条件,如上面的n==1,就是当我们化到求1的阶乘时,直接返回1

    ②每递归一次们都需要不断接近递出条件,如上面的函数,每次递归,n都是不断接近1的

    ③可以用递归解决的问题,我们都可以化为相同的循环代码来解决,递归太深可能会使栈溢出,所以我们要更具实际情况来决定该怎么解决问题


    列表和元组

    列表

    很多时候,我们需要存一系列数据,如:一个班所有人的成绩,这时候我们如果创建一个个变量,就会特别的麻烦

    于是,在Python中,我们列表,可以用一个变量来表示多个数据,它就类似于C++中的数组

    列表的创建
    # 我们有两种方式可以创建一个列表
    a = []
    b = list()
    #上述两种方式都是创建了一个空的列表
    #我们可以看看它们的类型
    print(type(a))
    print(type(b))
    

    这里可以看到,是列表(list)类型,它是Python的一个内置类型

    当然我们可以在创建的时候,让它存一些值

    a = [1,2,3,"hello"]
    #这里和数组不一样的是,列表存的值,可以是不同类型的,两个元素之间用,隔开
    #我们可以打印看看
    print(a)
    

    列表的访问和修改
    #这里我们通过[]这个下标访问操作符来访问列表
    # 先创建一个元素
    a = [1,2,3,4]
    #我们来访问下标为1的元素
    print(a[1])
    #在列表后面加上[],在[]中填写我们想访问的下标即可
    

    这里我们发现的打印的是2,其实列表和C++的数组一样,下标都是从0开始的

    #同时我们也可以用[]对列表元素进行修改
    a = [1,2,3,4]
    a[0] = 5
    print(a)
    

    其中我们[ ]中的数字可以写成负数

    a = [1,2,3,4]
    print(a[-1])
    

    这里我们可以看到访问4这个元素,其实写成-1,就相当于访问列表倒数第一个元素

    这里我们需要注意,我们写的下标一定要在有效范围之中哦

    列表的切片操作

    所谓的切片操作,就是截取列表中的一部分,取它的一个子列表

    a = [1,2,3,4]
    print(a[1:3])#这里我们用 列表名[前边界:后边界] 这样的格式来对列表进行切片
    #其中切片的下标范围是[前边界,后边界)
    #前后边界都可以省略,省略默认就是到最前或者最后了
    print(a[1:])
    print(a[:3])
    print(a[:])
    

    同时,我们还可以指定切片的步长

    a = [1,2,3,4,5,6,7,8,9]
    print(a[::2])#这样就是从第一个元素开始,每两个元素取一个
    #步长为负数的话就是从后向前
    print(a[::-1])
    

    这里注意,我们切片的时候,如果输入的下标超出范围不会抛出异常,而是会尽可能的去取

    列表的遍历

    遍历,就是把每个元素取出来,并进行操作,一般搭配循环

    之前我们有个len()这个函数,它也可以来求列表的长度

    # 这里我们用两种方法来遍历列表
    a = [1,2,3,4,5]
    #第一种,直接取出列表中的值给一个变量
    for elem in a:#之前我们说过,in后要是一个可迭代对象,我们的列表就是
        print(elem)
    print("-------")
    #第二种,通过下标遍历
    for i in range(0,len(a)):
        print(a[i])
    #这两种方法的不同在于,第一种对于elem操作,并不会影响a的元素
    #第二种,可以对a中的元素进行修改
    

    列表的插入(append,insert)
    #如果我们想在列表的后面加上一个元素的话
    #可以通过append()这个函数来进行
    a = [1,2,3,4,5]
    a.append("hello")#我们在后面插入一个hello
    print(a)
    

    #如果我们想在任意位置插入一个元素
    #可以使用insert()
    a = [1,2,3,4,5]
    a.insert(1,"hello")#这样就是在下标为1的位置插入hello
    print(a)
    #当然如果我们给出一个超范围的下标,会直接插在第一个或者最后一个
    

    像上面这两个函数,需要搭配对象来使用的,我们叫它们方法

    列表元素的查找(in,index)
    a = [1,2,3,4]
    #我们会用in来判断一个元素在不在列表中
    print(1 in a)#这段代码的含义是,1在不在a中,在返回True,不存在返回False
    print(1 not in a)# 1 是否不存在a中
    

    #此外,如果我们想查询元素的下表可以使用index()
    a = [1,2,3,4]
    print(a.index(2))#2在不在a中,在返回下标,不在抛出异常
    

    列表元素的删除(pop,remove)

    这里我们介绍三种删除

    # 尾删
    a = [1,2,3,4]
    a.pop()#直接删除最后一个元素
    print(a)
    

    #按下标删
    a = [1,2,3,4]
    a.pop(1)#删除下标为1的元素
    print(a)
    

    #按值删除
    a = ["aa","bb","cc"]
    a.remove("bb")#删除列表中的bb
    print(a)
    

    列表的拼接(+,extend,+=)

    类似于字符串,我们的列表也是可以进行拼接的,这里我们介绍三种拼接方式

    #使用+拼接
    a = [1,2]
    b = [3,4]
    c = b + a
    print(c)
    #这种拼接方式不会对a,b造成什么影响
    

    #使用extend拼接
    a = [1,2]
    b = [3,4]
    a.extend(b)#把b接到a的后面
    #我们来看看这时候a和b
    print(a)
    print(b)
    

    这时候发现,对a列表还是有影响的

    #使用+=
    a = [1,2]
    b = [3,4]
    a += b #效果类似于第二种
    print(a)
    


    元组

    元组,和列表一样,也是来存储多个数据的,包括它的操作都和列表一样

    不一样的是元组是不可变的,就是我们不能对元组中的元素进行改变

    元组的创建

    和列表一样,元组也有两种创建方式

    #我们用()来表示一个空元组
    a = ()
    b = tuple()
    #我们看看它的类型
    print(type(a))
    print(type(b))
    #同样,我们也可以在创建的时候存元素进去
    

    元组中的操作

    元组是不可变的,所以列表中的extend append pop这些对元组有影响的操作是不可以的

    其他操作和列表一样

    这里注意,拼接中的+可以使用哦


    字典

    字典是一个用来存键值对的数据结构

    什么是键值对呢,目前我的理解来说,就是两个相互联系数据,一个做键:key,一个做值:value;通过键可以立马找到值,就像每个人的学号一样

    字典中可以同时包含多个键值对,但是要求键(key)是不能重复的

    字典的创建

    # 这里我们还是有两种方式创建字典
    a = {}
    b = dict()
    #我们来看看它的类型
    print(type(a))
    print(type(b))
    

    #这里我们看看怎么在创建的时候存键值对
    a = {"id":1,"name":"zhangsan"}#我们还是用逗号区分元素,每个元素前面写key,后面写value,中间用:分开
    #但是我们为了更好地观察元素一般这样写
    a = {
        "id":1,
        "name":"zhangsan",#这里的逗号可有可无
    }
    print(a)
    

    这里的key类型是有限制的,而value是任意类型的哦

    字典中的查找操作

    这里我们介绍两种查找

    #查找key
    a = {
        "id":1,
        "name":"zhangsan",
    }
    print("id" in a) #id是否在字典a的key中,在返回True,不存在返回False
    

    #根据key获取value
    a = {
        "id":1,
        "name":"zhangsan",
    }
    print(a["id"])#[]中写key,获取对应的value,输入无效key会抛出异常
    

    这里博主觉得,有点像把列表的下标换成其他类型的,不是0,1,2,3了

    字典元素的增加和修改

    a = {
        "id":1,
        "name":"zhangsan",
    }
    #我们用[]进行新增元素
    a["score"] = 90 # []中写key,=后面写对应的value
    print(a)
    #我们还是用[]进行修改
    a["score"] = 100
    print(a)
    #对于没有的键值对是新建
    #对于有的键值对是修改
    

    字典元素的删除

    a = {
        "id":1,
        "name":"zhangsan",
    }
    #我们用pop进行删除
    a.pop("name")#()中写key,就可以删除对应的键值对
    print(a)
    

    字典的遍历

    字典的遍历有很多方法

    #我们先说最常见的for遍历
    a = {
        "id":1,
        "name":"zhangsan",
        "score":100
    }
    for key in a:
        print(key,a[key])#类似列表,我们一样可以用for来遍历字典的键和值,同样字典也是可迭代对象
        #但是我们只能获取key,之后再根据key访问到value
    

    #用keys获取字典中所有的key#用keys获取字典中所有的key
    a = {
        "id":1,
        "name":"zhangsan",
           "score":100
    }
    print(a.keys())
    


    这里我们发现出来一个类似于列表的数据

    #我们来看看它的类型
    a = {
        "id":1,
        "name":"zhangsan",
           "score":100
    }
    print(type(a.keys()))
    #其实我们就要可以把他当作列表那样取操作
    for elem in a.keys():
        print(elem)
    
    

    下面的values和它一样

    #用values获取字典中所有的value
    a = {
        "id":1,
        "name":"zhangsan",
           "score":100
    }
    print(a.values())
    

    但是下面就有点不一样了

    #用items获取字典中所有的键值对
    a = {    
        "id":1,
         "name":"zhangsan",
         "score":100
        }
    print(a.items())
    


    可以发现出来一个类似列表里每个元素是元组的数据
    其实我们同样可以把他当作列表操作

    a = {
        "id":1,
         "name":"zhangsan",
         "score":100
        }
    #但是对于每个元素,我们需要按多元赋值来
    for key,value in a.items():
        print(key,value)
    

    合法key的类型

    之前我们说过key的类型是有要求的

    对应key来说,它需要是一个可哈希的类型

    直白点来说就是,key需要是一个不可变的类型

    在Python中我们常见的整数,字符串,浮点数…这些基本数据类型都是不可变的,包括元组,他们都可以作为key的类型

    那么有哪些不能呢:列表,字典…这些都不可以(更多的可以关注Python文档)


    总结

    这一部分,我们介绍了函数,列表,元组,字典,对Python有了更多的认识,其中博主认为,后三者有相似的地方,可以关联记忆

    如果大家有什么建议和补充,欢迎评论留言

    作者:Emilia486.

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python基础语法详解(进阶篇)

    发表回复