四级考级要点

函数

函数的概念

  • 函数是一段具有特定功能的、可重用的语句组
  • 使用函数的主要目的是减低编程难度和代码重用
  • 函数能完成特定的功能,对函数的使用不需要了解函数内部实现原理,只要了解函数的输入输出方式即可
  • 函数的定义必须在主程序调用语句之前出现

定义函数

定义函数的格式如下:

def 函数名(0或多个参数):
    函数体(多行代码)

说明:函数名和变量的命名规则一致

函数的使用

def user():  #def 关键字后面加函数名定义函数,定义以英文冒号结尾
    print("Hello World")   #函数体,用来写该函数需要完成的功能的代码
user()    #使用函数名()的方式调用函数

运行结果

Hello World

形参和实参

实参(实际参数)是一个实实在在存在的参数,是实际占用内存地址的,也可以认为实参是调用函数是传递的参数;

形参(形式参数)只是意义上的一种参数,是不占用内存地址的,在函数定义时的参数。

(1)位置实参

在调用函数时,必须将每个实参都关联到函数定义中的每一个形参,最简单的关联方式就是基于实参的位置(顺序)。

def f(x,y,z):      #首先在定义函数时传入3个形参x、y、z
    print(x,y,z)
f(3,2,1)    #在调用该函数时,通过位置实参的方式,将实参映射到形参,一一对应,即x=3,y=2,z=1

运行结果:

3 2 1

需要注意,如果使用位置实参的方式传值,传入的实参个数必须与形参相同,否则运行程序会报错。

(2)关键字实参

关键字实参是通过“关键字=值”的方式传值,就不需要考虑函数调用过程中形参的顺序。同一个参数不能传两个值。

def f(x,y,z):
    print(x,y,z)
f(x=1,y=2,z=3)     #通过“关键字=值”的方式,将实参与形参关联映射,不需要考虑形参的顺序,顺序也可以改变,即y=2,z=3,x=1,运行的结果不会发生改变

运行结果:

1 2 3

关键字实参,不用考虑参数的顺序,如下三种方式,传递的参数是一样的

f(x=1,y=2,z=3) 
f(y=2,x=1,z=3) 
f(z=3,x=1,y=2)

(3)既有位置实参,又有关键字实参

def f(x,y,z):
    print(x,y,z)
f(1,y=2,z=3)    #混用两种方式时,位置实参必须放在关键字实参之前,否则运行程序会报错,如1,y=2,3或者y=2,1,3都不可行

运行结果:

1 2 3

注意:位置实参必须放在关键字实参前面

(4)默认值

定义函数时,也可以指定形参的默认值,如果在调用函数时给函数提供了实参,Python将使用指定的实参值;否则将自动调用形参的默认值。因此,如果给形参指定了默认值,调用时可以不给它传值。使用默认值可以简化函数的调用。

def f(x,y=2):    #定义函数时在这里给形参设置了默认值=2
    print(x,y)    
f(1)    #在调用此函数时,只传入了一个实参,义的值就会使用默认值

运行结果:

1 2

还可以在调用时更改默认值,如下例所示。

def f(x,y=2):
    print(x,y)
f(1,3)    #在调用该图数时,给设置了默认值的形参立再次赋值,运行结果会使用新传入的实参值

运行结果:

1 3

在使用形参默认值时需要注意:在形参列表中必须先列出没存默认值的形参,再列出有默认值的形参。

(5)列表和字典

当不确定需要传入的值是多少时,在定义形参时,可以使用*args(列表)、**kwargs(字典)来表示。

def f(*args,**kwargs): 
        print(args)
        print(kwargs)
f(1,2,3,4,5,y=1,z=2)    #y=1,z=2作为键值对被传给kwargs

运行结果:

(1, 2, 3, 4, 5)
{'y': 1,'z': 2}

说明:

位置参数作为一个元组传递给列表参数,关键字参数作为一个字典传递给字典参数

匿名函数

格式如下:

函数名 = lambda 参数列列表 : 表达式

例如:

>>> myFun = lambda r:2*3.14*r
>>> myFun(5)
31.400000000000002

注意

  • lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。

  • lambda表达式能接收任何数量的参数但只能返回一个表达式的值。

  • lambda表达式需要定义变量保存

函数的返回值

函数用return 语句将值返回调用函数的代码行,未使用return语句返回,则默认返回None。

下面是一个简单的程序,用于接收姓氏和名字,然后返回完整的人名信息。

def name(first_name,last_name):
    full_name=first_name+" "+last_name
    return full_name
print(name("zhangsan","san"))

运行结果:

zhangsan san

函数可以返问任何类型的值,包括字典、列表这样较复杂的数据结构。

全局变量和局部变量

一般定义在程序最开始处的变量称为全局变量,而在函数中定义的变量称为局部变量。

可以简单理解为,无缩进的为全局变量,有缩进的是局部变量。

全局变量的作用域是整个程序,而局部变量的作用域是函数内部。当程序运行时,首先会找程序内部有没有局部变量,如果有,则调用;如果没有,才去调用全局变量。

name='zhang'    #全局变量
def f():
    name="li"    #局部变量
    print(name)
f()
print(name)        #打印全局变量name的值

运行结果:

li
zhang

可以通过global关键字,通过局部变量修改全局变量的值,如下例所示。

name="zhang"    #定义全局变量
def f():
    global name    #在函数内部,通过global关键字,通过局部变量修改全局变量的值
    name="li"
    print(name)
f()                #打印局部变量name的值
print(name)        #打印全局变量name的值

运行结果:

li
li

在运行结果中可以明显看出,使用global关键字后,在定义局部变量的同时也修改了全局变量的值。

global与nonlocal的区别:

global关键字用来在定义局部变量的同时,修改全局变量的值;

nonlocal关键字用来在函数或局部作用域使用外层(非全局)变量。

递归与递推

递归

在定义一个函数或过程时,如果出现调用自身的成分,则称为递归。

递归算法的实现要点:

  • 边界条件和边界值(出口)
  • 递推关系(公式)

递归函数的一般写法

def f(n):
    if 边界条件:
          return 出口值
    else:
         return 递推关系

斐波那契数列

斐波那契数列指的是这样一个数列:1 、1、2、3、5、8、13、21、34......其第1项、第2项为1,从第3项开始,每一项是前两项之和。

边界条件为:f(1)=1,f(2)=1

递推关系为:f(n) = f(n-1) + f(n-2)

由以上边界条件和递推关系,可以得到如下函数:

def f(n):
    if n==1 or n==2: #边界条件
          return 1
    else:
         return f(n-1)+f(n-2)  #递推关系
print(f(6))

递推

递推是序列计算中的一种常用方法。它是按照一定的规律来计算序列中的每一项,通常是通过计算前面的一些项来得出序列中指定项的值,如非常有名的斐波那契数列,python程序如下。

def f(n):
    a=b=c=1
    for i in range(n-2):
        c=a+b
        a=b
        b=c
    return c
print(f(6))

递归和递推算法的比较

  • 递归算法简单易懂,但速度慢,对效率要求高的代码,不推荐使用

  • 递推算法写起来麻烦些,但速度很快

分治算法

分治算法的概念

:将一个复杂的问题分成两个或更多个相同或相似的子问题,再把子问题分成更小的子问题。

治:最后子问题可以简单地直接求解。

:将所有子问题的解合并起来就是原问题的解。

分治算法的特征

(1)该问题的规模缩小到一定的程度就可以容易地解决。

(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优结构性质。

(3)该问题分解出的子问题的解可以合并为该问题的解。

(4)该问题所分解出的各个子间题是相互独立的,即子问题之间不包含公共的子子问题。

  • 快速排序是典型的分治算法

算法优化

时间复杂度

一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数f(n),算法的时间度量记作T(n)=O((n)),它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长关系,称作算法的渐进时间复杂度,简称时间复杂度。

一般规律如下:

  • 没有循环的算法:时间复杂度为O(1)
  • 一层循环的算法:时间复杂度为O(n)
  • 两层循环的算法:时间复杂度为O(n^2^)

以上只是一般情况,如下特殊情况:

i=1 
n=100 
while i<n:
    i=i*2

量级为对数阶,2^x^=n,所以时间复杂度为O(log~2~n)。

小结

平均运行时间是期望的运行时间,最坏的运行时间是一种保证。我们提到的运行时间都是最坏的运行时间。

空间复杂度

空间复杂度是指算法被编写成程序后,在计算机中运行时所需存储空间大小的度量,记作S(n)=O(f(n)),其中n为问题的规模或大小。

存储空间一般包括3个部分∶

(1)输入数据所占用的存储空间;

(2)指令、常数、变量所占用的存储空间

(3)辅助(存储)空间。

算法的空间复杂度一般指的是辅助空间。

一维数组a[n]的空间复杂度为O(n)。

二维数组a[n][m]的空间复杂度为O(n*m)。

第三方库(模块)的获取、安装与调用

第三方库的获取、安装方法

安装Python第三方库的3种方法为∶

(1)使用pip命令;

(2)集成安装方法;

(3)文件安装方法。

常用的pip指令如下。

pip install <第三方库名>∶安装指定的第三方库。

pip install --upgrade <第三方库名>∶将已经安装的第三方库更新到最新版本中。

--upgrade可以简写为-U ,pip install -U <第三方库名>

pip uninstall <第三方库>∶卸载指定的第三方库。

pip download <第三方库>∶下载但不安装指定的第三方库,作为后续的安装基础。

pip show <第三方库>∶列出指定第三方库的详细信息。

pip search <第三方库>∶根据关键词在名称和介绍中搜索第三方库。

pip list∶列出当前系统已经安装的第三方库。

python -m pip install --upgrade pip∶ 升级 pip(Python 3.4之后的版本都自带了pip)。

第三方库的导入方法

1. import 模块名1 [as别名1] ,模块名2 [as别名2] ,…

使用这种语法格式的import语句,会导入指定模块中的所有成员(包括变量、函数、类等)。当需要使用模块中的成员时,只需将该模块名(或别名)作为前缀,如下例所示。

>>> import math
>>> math.pi
3.141592653589793

注意,用[]括起来的部分,可以使用,也可以省略。

>>> import math as m
>>> m.pi
3.141592653589793

2. from 模块名 import 成员名1 [as别名1] ,成员名2 [as别名2] ,…

使用这种语法格式的import语句,只会导入模块中指定的成员,而不是全部成员。同时,当程序中使用该成员时,无须附加任何前缀,直接使用成员名(或别名)即可。

from math import *  #导入模块中的所有成员
Copyright © all right reserved,powered by Gitbook该文件修订时间: 2023-06-25 09:20:14