• Python学习04、函数、变量的作用域、链式访问、嵌套调用、函数递归、参数默认值、关键字参数、列表和元组、切片操作、遍历


    函数

    数学中的函数相当于一种映射关系,参数通过一系列数学变换来计算生成一个结果

    编程中的函数和数学中的函数是相似的,编程中的函数指的是一段可以被重复使用的代码

    函数的格式

    1.函数定义(分配任务)

    def关键字,注意之前提到的硬性规则和软性规则

    def 函数名(形参列表):

            函数体(这一部分要带有一级缩进,带有缩进的代码,才是函数内部的语句)

            return 返回值(函数的返回值,函数执行到retun,意味着执行完了,return后面的值,就是函数的返回值,return语句并不是必须的,可以有,也可以没有)

    形参列表中可以有多个形参,多个形参(形式参数)间使用逗号分隔

    2.函数调用(开始执行任务,完成任务)

    第一种:

    函数名(实参列表,实际参数,简称实参,此处写的实参的个数要和形参的个数匹配)

    第二种:

    返回值 = 函数名(实参列表)

    Python中要求,函数定义写在前面,函数调用写在后面--先定义,后调用

    推荐函数名这么写calc_Sum,都可以

    PEP8是Python里面一套非常流行的程序规范,也是写代码中的一些软性要求

    在C++/Java里,不光要求形参和实参的个数匹配,类型也要匹配

    但是在Python里,只是要求个数,对类型没有要求(因为Python里存在动态类型)

    所以Python里传什么都行,可以顺利运行,顺利打印出来

    Python里也可以写return

    def add(x, y):

            return x + y

    只要保证函数体里的操作能正常运行,就可以

    # 在实际开发中,一般都倾向于第二种写法,有一个通用的编程原则:一个函数只做一件事!
    # 这样一旦后续需要改变和用户的交互方式,第二种写法就更有优势。当前是通过控制台和用户交互的
    # 让逻辑和交互/界面能够分离,进一步的好处有:解耦合(避免藕断丝连的影响)。
    # 在一个稍微复杂一些的程序中,经常会涉及到很多个模块,模块之间可能要进行交互,有些交互耦合性比较强,有些交互耦合性比较弱
    # 我们期望尽量通过良好的涉及来让耦合降低。
    # 耦合:一方产生一些变动,对另一方产生的影响
    
    
    # 这种情况不算是有多个return语句的
    # def test():
    #     return 1
    #     return 2
    #
    # # 一般多个return语句是搭配 分支语句/循环语句的
    # def is_odd(num):
    #     """
    #     用来判断是不是奇数,如果是奇数,则返回True,如果不是返回False
    #     :param num: 要判定的数
    #     :return: 返回True/False来表示是不是奇数
    #     """
    #     if num % 2 == 0:
    #         return False
    #     else:
    #         return True
    #
    # print(is_odd(10))
    # print(is_odd(19))
    
    
    
    # 写一个函数,返回平面上的一个点
    # 横坐标,纵坐标
    # def get_point():
    #     x = 10
    #     y = 20
    #     return x, y
    # # 就可以一次返回多个值了
    # # 多元赋值
    # a, b = get_point()
    #
    # #虽然现在返回了多个值,但是我只想用其中一部分,不关注其他的,可以使用下划线来占位:
    # _, d = get_point()# 可以写个下划线占位

    函数的返回值

    一个函数中是可以有多个返回语句的

    当执行到return时就不再往下执行了,而是回到了调用位置(函数结束)

    一个函数可以返回多个值,比起C++/Java好很多,因为这两种语言调用一个函数一次只能返回一个值。如果C++想返回多个值,需要通过输出型参数(指针/引用)。如果Java想要返回多个值,需要把多个值给包装成一个对象,返回这个对象。而Python直接用逗号分割就可以了

    但是有时候,虽然返回了多个值,但是我们只想用其中的一部分,不关注其他的,可以使用下划线来占位

    1. # 写一个函数,返回平面上的一个点
    2. # 横坐标,纵坐标
    3. def get_point():
    4. x = 10
    5. y = 20
    6. return x, y
    7. # 就可以一次返回多个值了
    8. # 多元赋值
    9. a, b = get_point()
    10. #虽然现在返回了多个值,但是我只想用其中一部分,不关注其他的,可以使用下划线来占位:
    11. _, d = get_point()# 可以写个下划线占位。这里把y直接赋给了d

    当没有return时,执行到末尾也就结束了 

    变量的作用域

     链式调用

    把一个函数的返回值,作为另一个函数的参数

     嵌套调用

    一个函数的函数体内部,还可以调用其他函数。就叫做嵌套调用

    一个函数里面可以嵌套调用任意多个函数

    def a ():
        print ( " 函数 a" )
    def b ():
        print ( " 函数 b" )
        a ()
    def c ():
        print ( " 函数 c" )
        b ()
    def d ():
        print ( " 函数 d" )
        c ()
    d ()
    def a ():
        print ( " 函数 a" )
    def b ():
        a ()
        print ( " 函数 b" )
    def c ():
        b ()
        print ( " 函数 c" )
    def d ():
        c ()
        print ( " 函数 d" )
    d ()

    函数递归

    函数自己调用自己

    递归的两个要素:

    1.递归结束条件

    2.递归的递推公式

    类似于数学归纳法:

    1.初始条件

    2.递归公式

    递归的缺点:

    1.执行过程非常复杂,难以理解

    2.递归代码容易出现“栈溢出”的情况

    3.递归代码一般都是可以转换成等价的循环代码的。并且循环的版本通常运行速度要比递归的版本有优势(函数调用也是有开销的)既慢又占空间

    递归的优点:

    代码非常简洁,尤其是处理一些“问题本身就是通过递归的方式定义的”

    数据结构中的二叉树本身就是通过递归的方式定义的额,有时候处理二叉树就需要用到递归解决问题

    参数默认值

    Python中的函数,可以给形参指定默认值

    带有默认值的参数,可以再调用的时候不传参

    关键字参数

    按照先后顺序来传参,这种传参风格称为“位置参数”,这是各个编程语言中最普遍的方式。

    关键字传参,按照形参的名字来进行传参

     位置参数和关键字参数还能混着用,只不过混着用的时候要求位置参数在前,关键字参数在后

    关键字参数,一般也就是搭配摩恩参数来使用的。一个函数,可以提供很多的参数,来实现对这个函数的内部功能做出一些调整设定,为了降低调用者的使用成本,就可以把大部分参数设定出默认值(导出默认值)

    当调用者需要调整其中的一部分参数的时候,就可以搭配关键字参数来进行操作

    函数小结:

    函数的定义

    函数的调用

    函数的参数传递过程

    函数的执行流程(进去好近,出来不好出)

    列表和元组

    变量一定程度上代表着内存 空间,用来表示/存储数据

    如果表示的数据少,直接定义几个变量就行了

    那么需要表示的数据很多时,该怎么办呢?

    列表可以管理很多元素

    在Python中,列表和元组(类似于其他编程语言中的“数组”)可以用一个变量来表示很多个数据

    列表和元组,大部分功能都是差不多的,但是有一个功能有非常明显的区别:

    列表是可变的,创建好了之后,随时能改

    元组是不可变的,创建好了之后,改不了,要想改,就只能丢弃旧的,搞个新的

    列表可变,元组不可变

    创建列表:

    1.直接使用字面值来创建

    在Python中[ ]就表示一个空的列表

    a = [ ]

    2.使用list()来创建

    b = list()

    推荐使用[]来创建列表,因为[]能方便我们在创建列表时指定初始值,元素之间用,分割

    a = [1, 2, 3, 4, 5]

    C++/Java里要求一个数组里只能存相同类型的变量,而Python里可以在一个列表里放不同类型的变量

    列表的下标访问:

    我们可以通过下标访问的方式(用到下标访问运算符[])来获取到列表中的元素

    a = [ ]

    把[]放到一个列表变量的后面,同时[]里写上一个整数,此时它就是下表访问运算符,[]中间写的这个证书,就是称为“下标”或者“索引”

    下标是从0开始计数的

    当我们下标超出有效范围时,就会出现异常

    可以使用len来测列表长度

    a = [1, 2, 3, 4]

    print(len(a))

    len可以传字符串,列表,元组,字典,自定义的类...一个函数能支持这么多类型,背后的原理:动态类型

    Python中的下标其实还可以写成负数,例如写成-1,其实等价于len(a)-1

    # 下标为-1时,其实等价于len(这个列表)-1
    a = [1, 2, 3, 4]
    print(len(a))
    print(len(a) - 1)
    print(a[len(a) - 1])
    print(a[-1])
    # -1这个下标就是倒数第一个元素

    结果:

    4

    3

    4

    4

    也可以认为-1这个下标就是倒数第一个元素

    切片操作:

    一次取出一组连续的元素

    # 关于切片操作的基本使用
    a = [1, 2, 3, 4]
    print(a[1:3])

    切片操作中,[]里面有两个数字,表示了一段区间。

    1表示开始区间的下标,3表示结束区间的下标。取下标1到3的元素,但是这里包含1不包含3,前闭后开

    切片操作是可以省略前后的两个边界的

    切片操作是一个比较高效的操作,进行切片的时候,只是取出了原有列表中的一个部分,并不涉及到“数据的拷贝”。假设有一个很大的列表进行切片,切片的范围也很大,即使如此,切片操作仍然非常高效(没有去拷贝什么的)

    切片操作还可以指定“步长”,

    # 切片操作中指定步长的操作
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(a[::1])# 这里的1就是步长,指每次走的长度
    print(a[::2])
    print(a[1:-1:2])
    print(a[::-2])# 步长的数值还可以是负数,当步长为负数时,意思是从后往前取

    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    [1, 3, 5, 7, 9]
    [2, 4, 6, 8]
    [10, 8, 6, 4, 2]

    # 当切片中的范围超出有效下标之后,不会出现异常!而是尽可能的把符合要求的元素给取到
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(a[1:100])
    

    [2, 3, 4, 5, 6, 7, 8, 9, 10]

    当然,单纯访问时越界是会报错的

    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    # print(a[1:100])
    print(a[100])

    Traceback (most recent call last):
      File "C:\Users\14534\Desktop\Python\code12.py", line 85, in
        print(a[100])
    IndexError: list index out of range

    遍历

    把一个列表里的每个元素都一次取出来,并进行某种操作,不重不漏

    遍历往往要搭配循环

    在列表中插入元素

    # 使用append往列表末尾新增元素
    a = [1, 2, 3, 4, 5]
    # 此处的append是搭配列表对象a来一起使用的,而不是作为一个独立的函数
    # 这种要搭配对象(变量)来使用的函数,也叫作“方法”
    # type,print,input,len,自定义函数...都是独立的函数
    a.append(5)
    a.append("hello")
    print(a)
    
    b = [5, 6, 7, 8]
    b.append("world")
    print(b)
    
    # 使用insert往列表的任意位置来新增元素
    a = [1, 2, 3, 4]
    a.insert(1, "hello")# 第一个参数是要往哪个位置去插,第二个参数是要插入的元素是什么
    a.insert(100, "hello")# 并不是报错或扩展列表,而是插到末尾
    print(a)

    在列表中查找元素

    # 使用in来判断某个元素是否在列表中存在
    a = [1, 2, 3, 4, 5]
    print(1 in a)# 存在返回True,不存在返回False
    print(17 in a)
    print(1 not in a)
    print(10 not in a)
    
    # 使用index来判断当前元素在列表中的位置,得到一个下标
    a = [1, 2, 3, 4, 5]
    print(a.index(2))# 看2存不存在,如果存在,就返回2的下标,如果不存在,会抛出异常

    删除列表元素

    # 删除元素pop,remove
    a = [1, 2, 3, 4, 5]
    a.pop()# 不传参的话删除掉的是末尾元素
    print(a)
    
    # 使用pop还能删除任意位置的元素,pop的参数可以传一个下标过去
    a = [1, 2, 3, 4]
    a.pop(1)# 删除该下标元素
    print(a)
    
    # 使用remove来按照值来删除
    a = ["aaa", "bbb", "ccc", "ddd"]
    a.remove("ccc")
    print(a)

    列表的拼接

    # 使用“+”针对两个列表进行拼接
    # a = [1, 2, 3, 4, 5]
    # b = [6, 7, 8, 9, 10]
    # c = a + b# 谁在前,谁的内容就在前,谁在后,谁的内容就在后
    # print(c)
    
    # 使用extend来进行拼接
    # 这个拼接是把后一个列表的内容拼接到前一个列表里面,这样做会修改原来的列表
    # a = [1, 2, 3, 4, 5]
    # b = [6, 7, 8, 9, 10]
    # a.extend(b)
    # c = a.extend(b)
    # print(a)
    # print(b)
    # print(c)# 打印出的结果是None
    # # 关于None,这是一个特殊的变量值,表示啥都没有
    # # extend其实是没有返回值的,如果拿变量接收没有返回值的返回值,就什么都没有
    # # None非常类似于C里面的NULL,或Java里的null,或C++里的nullptr
    
    # 使用+=来进行拼接
    a = [1, 2, 3, 4]
    b = [5, 6, 7, 8]
    a += b
    print(a)
    print(b)
    # 那么它和extend有什么区别呢?
    # a = a + b相当于把a原先的值被a+b覆盖了,相比较之下比较低效
    # extend更高效

     元组

    创建元组

    # 创建元组
    # a = ()# 表示一个空的元组
    # print(type(a))
    # b = tuple()# 空的元组
    # print(type(b))
    # # 创建元祖的时候,可以指定初始值
    # a = (1, 2, 3, 4)
    # print(a)
    
    # 元组中的元素也可以是任意类型的
    # a = (1, 2, True, "hello", [])
    # print(a)
    
    # 通过下标来访问元组中的元素,下表也是从0开始的,到len-1结束
    # a = (1, 2, 3, 4)
    # print(a[1])
    # print(a[-1])
    # print(a[100])# 抛出异常,下标越界
    
    # 通过切片来获取元组中的一部分
    # a = (1, 2, 3, 4)
    # print(a[1:3])
    #
    #
    # # 也可以使用for循环等方式来遍历元素
    # a = (1, 2, 3, 4)
    # for elem in a:
    #     print(elem)
    #
    #
    # # 也可以使用in判断元素是否存在,使用index来查找元素的下标
    # a = (1, 2, 3, 4)
    # print(3 in a)
    # print(a.index(3))
    #
    # # 可以使用+来拼接两个元组
    # a = (1, 2, 3, 4)
    # b = (5, 6, 7, 8)
    # print(a + b)
    # 注意,以上操作都是没有改变元组的,元组只要创建好,就不能改变了。虽然a + b是把元组拼接,但是a,b的本体是没有改变的
    
    # 元组只是支持读操作(只读),不支持修改
    a = (1, 2, 3, 4)
    # 所以以下这些都不行
    # a[0] = 100
    # a.append(5)
    # a.pop(0)
    # a.extend()
    # 这些涉及修改元组的都是不可行的,元组能读但是不能修改。这是它和列表的很大的区别
    
    # 当进行多元赋值的时候,其实本质上是按照元组的方式来进行工作的
    def get_point():
        x = 10
        y = 20
        return x, y
    
    x, y = get_point()# 构造新元组
    print(type(get_point()))# 这里的get_point()就是元组
    
    # 那么为什么有了列表还要有元组呢?
    # 既然列表已经可读可修改了,为什么还要有元组这个只可读的呢?
    # 因为协同开发的时候,有时候需要程序员1实现一些功能,提供给程序员2来使用,1写好一些函数,让2去调用。
    # 2在使用函数,在传参时,可能纠结一个问题,把参数传过去了,1的函数里面是否会把2的参数的内容给改了呢?
    # 当我们使用元组作为参数时,就可以避免这样的纠结
    # 元组不能修改(也称为不可变对象)。不可变对象是可以哈希的!(一会后面再介绍)不可变对象可以哈希,意思是:它可以作为字典的那个键。
    # 不可变对象天然就是线程安全的
    

  • 相关阅读:
    Ego-Swarm编译与运行
    QT信号槽实现分析
    车辆管理怎么做?这六个车辆管理系统能帮到你!
    Debian11之基于kubeadm安装K8S集群
    java计算机毕业设计基于安卓Android/微信小程序的小区智能超市购物商城APP
    两级页表(单级页表存在的问题,两级页表的地址转换)
    c#开发和学习(c#编写windows服务)
    计算方法/数值分析 期末复习整理
    基于PHP的二手车交易系统的设计与实现
    【单片机毕业设计】【mcuclub-jk-006】基于单片机的医院输液的设计
  • 原文地址:https://blog.csdn.net/weixin_60320290/article/details/126690204