目录
1.函数
1.1 引入
# 求1~100的和
theSum = 0
for i in range(1, 101):
theSum += i
print(theSum)
# 求300~400的和
theSum = 0
for i in range(300, 401):
theSum += i
print(theSum)
# 求1~1000的和
theSum = 0
for i in range(1, 1001):
theSum += i
print(theSum)
以上三段代码均需要进行求和操作,故而可以提取其中的求和功能编写为求和函数:
# 使用函数进行求和操作
# 定义一个求和函数
def calc_sum(begin,end):
theSum = 0
for i in range(begin, end+1):
theSum += i
print(theSum)
# 调用函数
# 求1~100的和
calc_sum(1,100)
# 求300~400的和
calc_sum(300,400)
# 求1~1000的和
calc_sum(1,1000)
1.2 语法格式
1.2.1 函数的定义
def 函数名(形参列表):
函数体
return 返回值(可有可无)
注:① def 即 define ,意为定义;
② 形参列表中可以有多个形参,多个形参之间使用逗号分隔;
1.2.2 函数的调用
(1)函数名(实参列表)
(2)返回值 = 函数名(实参列表)
注:① 实参的个数要与形参的个数匹配;
② 函数定义写在前,函数调用写在后;
1.3 函数的返回值
编写代码求begin至end之间的整数之和:
代码1:
def calc_sum(begin, end):
theSum = 0
for i in range(begin, end+1):
theSum += i
print(theSum)
calc_sum(1, 100)
代码2:
def calc_sum(begin, end):
theSum = 0
for i in range(begin, end+1):
theSum += i
return theSum
result = calc_sum(1, 100)
print(result)
对比以上两个代码可发现,相对于代码1,代码二将calc_sum函数内部功能从计算与打印改编为只计算不打印,并将计算结果作为返回值,在函数外再进行打印。
(1) 一个函数可以有多个return 语句(一般都搭配条件或循环语句):
def is_odd(num):
if num % 2 == 1:
return True
else:
return False
print(is_odd(3))
print(is_odd(18))
(以判断奇数为例)
(2)执行到return 语句,函数就会立即执行结束,回到调用位置:
def is_odd(num):
if num % 2 == 1:
return True
return False
print(is_odd(3))
print(is_odd(18))
① 当条件满足时,return True 直接返回,就会避开执行return False语句,等效于前代码;
② 如果if语句里没有return 语句则不能写成此种形式,必须加上else语句;
(3)一个函数是可以一次返回多个返回值的,使用 , 来分割多个返回值:
对于C++、Java,调用一个函数一次只能返回一个值。
def get_point(x, y):
return x, y
a, b = get_point(10, 20)
print((a, b))
(以#编写程序返回平面上的一个点为例)
(4)如果只想关注其中的部分返回值,可以使用_来忽略不想要的返回值:
def get_point(x, y):
return x, y
_, b = get_point(10, 20)
1.4 变量作用域
(1)变量只能在所在函数内部生效
(2)在不同的作用域中,允许存在同名的变量
x = 10
def test():
x = 20
print(f"函数内部:{x}")
test()
print(f"函数外部:{x}")
输出结果如下:
(3)函数访问变量时会优先在函数局部变量中查找,若查找不到就会去上一级作用域中寻找:
x = 10
def test():
print(f"x={x}")
test()
输出结果如下:
(3)global关键字
x = 10
def test():
x = 20
test()
print(f"x={x}")
运行如上代码时,编译器会认为函数内部的x = 20语句意为在函数内部创建了一个局部变量,在函数外部打印时,依然会打印全局变量,x=10;
x = 10
def test():
global x # 声明x为全局变量
x = 20
test()
print(f"x={x}")
加上global x 关键字声明x为全局变量后,就可以改变全局变量:x = 20了
1.5 函数的链式调用和嵌套调用
1.5.1 函数的链式调用
链式调用:用一个函数的返回值作为另一个函数的参数
def is_odd(num):
if num % 2 == 0:
return False
return True
def add(x, y):
return x + y
print(is_odd(add(3, 7)))
将add函数的返回值作为is_odd函数的参数;
1.5.2 函数的嵌套调用
嵌套调用:一个函数的函数体内部还可以调用其他函数
代码1:
def a():
print("function a")
def b():
print("function b")
a()
def c():
print("function c")
b()
def d():
print("function d")
c()
d()
输出结果为:
代码2:
def a():
print("function a")
def b():
a()
print("function b")
def c():
b()
print("function c")
def d():
c()
print("function d")
d()
输出结果为:
1.6 函数递归
函数递归:函数自己调用自己
以求阶乘为例:
代码1:使用循环:
def factor(n):
result = 1
for i in range(1, n+1):
result *= i
return result
print(factor(5))
代码2:使用递归:
def factor(n):
if n == 1:
return 1
return n * factor(n - 1)
print(factor(5))
注:(1)递归代码的两个要素:
① 递归结束条件 ② 递归的递推公式
(2)递归的缺点:
① 执行过程比较复杂
② 递归代码容易出现栈溢出的情况
③ 递归代码一般都可以转换成等价的循环代码,并且循环的版本通常运行速度要快于递归版本
(3)递归的优点:
代码非常简洁,尤其是处理一些问题本身就是通过递归的方式定义的,如数据结构中的二叉树。
1.7 参数默认值
python中的函数可以给形参指定默认值,带有默认值的参数在调用时可以不传参:
def add(x, y=10):
print(f"x={x},y={y}")
return x + y
print(f"x+y={add(10, 20)}")
print(f"x+y={add(10)}")
输出结果为:
注:① 带默认值的形参必须在形参列表的后面
(报错提示为:非默认参数在默认参数之后)
② 当某参数具有指定默认值时,在调用该函数时若没有指定实参,则采用该默认值,否则则采用指定实参;
1.8 关键字参数
在调用函数的时候,需要给函数指定实参,一般默认情况下是按照形参的顺序来依次传递实参的。
但是我们也可以通过关键字参数来调整这里的传参顺序,显式指定当前实参传递给哪个形参。
def test(x, y):
print(f"x={x}")
print(f"y={y}")
test(10, 20)
test(x=10, y=20)
test(x=20, y=10)
位置参数和关键字参数还可以混合搭配使用,只是混合搭配时要求位置参数在前,关键字参数在后。关键字参数一般是搭配默认参数来使用的,一个函数为了降低调用者的使用成本,可以将大部分参数设定为默认值。
2.列表
列表与元组类似于其他编程语言中的数组,是一种让程序员在代码中批量表示或保存数据的方式。二者大部分功能都是差不多的,区别在于列表是可变的,创建好了之后随时可以更改,元组是不可变的,创建好了之后无法修改,如要修改只能去旧开新。
2.1 创建列表
(1)直接使用字面值来创建
a = []
print(type(a))
(2)使用list()来创建
b = list()
print(type(b))
(3)在创建列表时,在[ ]中指定列表的初始值
c = [1, 2, 3, 4]
print(c)
(4)列表中可以存储不同类型的变量(与C++、Java要求一个数组只能存相同类型的变量不同)
d = [1, 'hello', True, [4, 5, 6]]
print(d)
上文四段代码的输出结果如下:
2.2 访问下标
对于列表可以通过下标访问的方式来获取并访问列表中的元素,需要使用到下标访问运算符[ ]:
(1)访问:
a = [1, 2, 3, 4]
print(a[2])
(2)修改:
a[2] = 100
print(a)
(3)获取列表长度:
print(len(a))
以上三段代码的输出结果如下:
注:① python中列表的下标是从0开始计数的,下标有效范围为0至长度-1,若下标超出有效范围,尝试访问就会出现异常:
a = [1, 2, 3, 4]
a[100] = 0
print(a)
试运行如上代码,报错如下:
(列表赋值下标超出范围)
② 区别a = [ ]与 a[ ] 的区别,a = [ ]是创建列表,a[ ]当a是一个列表变量同时[ ]中所填为一个整数时,即表示访问列表a中下标为2的元素;
③ 下标也可以是负数:如写成-1,意为len(a)-1:
a = [1, 2, 3, 4]
print(a[len(a)-1])
print(a[-1])
以上两段代码的输出结果均为4,可以将-1理解为倒数第一个元素,-2理解为倒数第二个元素;
2.3 列表的切片操作
通过下标操作是一次取出其中一个元素,通过切片则是一次取出一组连续的元素,相当于得到一个子列表。
(1)使用[ : ] 的方式进行切片操作:
① 切片操作中方括号内有两个数字表示一段区间,第一个数字表示开始区间的下标,第二个数字表示结束区间的下标,区间为前闭后开区间:
a = [1, 2, 3, 4]
print(a[1:3])
② 切片操作是可以省略前后区间数字的:
print(a[1:]) # 从起始边界的元素开始切片至尾
print(a[:len(a)]) # 从初始元素开始切片至后边界
print(a[:]) # 得到列表本身
③ 切片操作是一个比较高效的操作,进行切片的时候只取出了原有列表的一个部分,并不涉及到数据拷贝。
④ 切片操作也可以指定步长:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print(a[::2])
print(a[1::2])
print(a[::-1])
print(a[::-2])
print(a[-1::-2])
print(a[1:100:])
输出结果为:
注:当步长为负数时,意为从后往前取元素;
当切片的范围超出有效下标时也不会出现异常,而是尽可能的把符合要求的元素获取到;
2.4 列表的遍历操作
2.4.1 for循环遍历
a = [1, 2, 3, 4, 5]
for elem in a:
print(elem)
elem就代表了列表里的每个元素;
在该种遍历方式下,即使是进行了elem = elem+10 的操作,改变的也是elem,而非列表元素;
2.4.2 for循环+下标
a = [1, 2, 3, 4, 5]
for i in range(0, len(a)):
print(a[i])
这种遍历方式可以修改列表中的元素值:
a = [1, 2, 3, 4, 5]
for i in range(0, len(a)):
print(a[i]+10)
2.4.3 while循环+下标
a = [1, 2, 3, 4, 5]
i = 0
while i < len(a):
print(a[i])
i += 1
2.5 列表的插入操作
2.5.1 append(列表末尾)
a = [1, 2, 3, 4]
a.append(5)
a.append("hello")
print(a)
注:① append不是独立的函数,而是必须搭配对象来使用的方法,同时也表明append函数是针对哪个列表对象进行尾插;
② 在pycharm中实际输入上段代码时会有列表优化建议,此处是为了演示append用法,请忽略。
2.5.2 insert (任意位置)
(1)insert函数有两个参数,第一个为待插位置的下标,第二个为待插元素:
a = [1, 2, 3, 4]
a.insert(1, "hello")
print(a)
(2)当待插位置下标超出列表下标范围时,会自动更改为尾插操作:
a = [1, 2, 3, 4]
a.insert(1, "hello")
print(a)
a.insert(100, "world")
print(a)
上段代码输出结果为:
2.6 查找元素
2.6.1 使用in操作符
判断元素是否在列表中存在,返回值是布尔类型
a = [1, 2, 3, 4]
print(1 in a)
print(10 in a)
输出结果为:
附:还有not in操作符:
a = [1, 2, 3, 4]
print(1 not in a)
print(10 not in a)
输出结果为:
2.6.2 使用index方法:
查找元素在列表中的下标,返回值是一个整数,如果元素不存在,则会抛出异常
a = [1, 2, 3, 4]
print(a.index(2))
print(a.index(3))
输出结果为:
当待查元素 不存在时,就会报错:
在C++、Java中当查找失败时会返回-1,但是在python中允许存在-1下标,故而采取查找失败抛出异常的机制。
2.7 删除元素
2.7.1 pop方法
pop方法既可以尾删,也可以传参下标后进行任意位置的删除:
a = [1, 2, 3, 4]
a.pop()
print(a)
a.pop(1)
print(a)
输出结果为:
2.7.2 remove方法
remove可以按照值进行删除:
slist = ['aa', 'bb', 'cc', 'dd']
slist.remove('bb')
print(slist)
输出结果为:
2.8 连接列表
2.8.1 使用+拼接列表
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
c = a + b
d = b + a
print(c)
print(d)
输出结果为:
注:+拼接列表对原有列表的内容是不影响其发生改变的,只时拼接成了一个更大的列表;
2.8.2 使用extend方法
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a.extend(b)
print(a)
b.extend(a)
print(b)
c = a.extend(b)
print(c)
输出结果为:
注:① extend 没有产生新的列表,就是将b列表拼接在了a列表的后面;
② None表示空;
2.8.3 使用 +=
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a += b
print(a)
print(b)
输出结果为:
注:请区别extend与+=的区别:
a.extend(b)表示将列表b拼接在列表a的后面,相对更搞笑;
a += b表示 a=a+b,是将二者拼接成一个大列表,再赋值给a,这涉及到数据的拷贝构造,相对更低效;
a+=b 图示如下:
3.元组
元组与列表类似,此处仅做简单陈列:
3.1 创建元组
a = ()
print(type(a))
b = tuple()
print(type(b))
c = (1, 2, 3, 4)
print(c)
d = (1, "hello", True, [2, 3, 4])
print(d)
3.2 访问元素
a = (1, 2, 3, 4)
print(a[1])
print(a[-1])
# print(a[100]) # 抛出异常
3.3 元组切片
a = (1, 2, 3, 4)
print(a[1:3])
print(a[::2])
3.4 元组遍历
a = (1, 2, 3, 4)
# 法1:
for elem in a:
print(elem)
i = 0
# 法2:
for i in range(0, len(a)):
print(a[i])
3.5 元组元素查找
a = (1, 2, 3, 4)
print(3 in a)
print(a.index(3))
3.6 元组拼接
a = (1, 2, 3, 4)
b = (5, 6, 7, 8)
print(a+b)
注:(1)元组只支持访问读取的操作,不支持修改类操作:
类似于a[0]=100,a.append(5),a.extend(b),a.pop(0)之类的操作都是不支持的。
(2)当进行多元赋值时,本质是按照元组的方式来进行工作的:
def get_point():
x = 10
y = 20
return x, y
x, y = get_point()
print(type(get_point()))
输出结果为:
(3)元组不能修改,也就是一个不可变对象,不可变对象是可以哈希的。
相关知识后续继续介绍。