Python 基础语法 (2)【适合 0 基础】
1. 语法结构
1.01 代码块和缩进
(像 C++ / Java , 即使完全不写缩进,语法也不会报错,但对于 Python ,缩进就很重要)
代码块:指的是一组放在一起执行的代码
缩进:通常是 4 个空格或者 1 个 tab 来表示
Python 中用缩进表示代码块,不同级别的缩进, 程序的执行效果是不同的:
# 情况一
a = input("请输入一个整数: ")
if a == "1":print("hello")print("world")# 情况二
a = input("请输入一个整数: ")
if a == "1":print("hello")
print("world")# 情况一:print("world") 有一级缩进, 这个语句属于 if 内的代码块,和 if 条件有关
# 情况二:print("world") 没有缩进, 这个语句是 if 外的代码,和 if 条件无关
代码块内部也可以嵌套代码块:
a = input("请输入第一个整数: ")
b = input("请输入第二个整数: ")
if a == "1":if b == "2":print("hello")print("world")
print("Python")# print("hello") 有两级缩进, 属于 if b == "2" 条件成立的代码块
# print("world") 有一级缩进, 属于 if a == "1" 条件成立的代码块
# print("python") 没有缩进,和 if 条件无关
1.02 空语句
在 Python 中,空语句用于表示一个语法上需要但逻辑上不需要任何操作的地方。通常用 pass 关键字来实现。pass 并不会对程序的执行有任何影响, 只是占个位置, 保持 Python 语法格式符合要求
a = int(input("请输入一个整数:"))
if a != 0:pass # 如果没有 pass ,程序不符合 Python 语法,会报错
else:print("haha")
1.1 顺序语句
顺序语句是指按照代码的书写顺序逐行执行的语句。程序从上到下依次执行每一条指令,没有跳过或重复的行为。默认情况下, Python 的代码执行顺序是按照从上到下的顺序, 依次执行的。
print("1")
print("2")
print("3")
# 执行结果一定为 "123", 而不会出现 "321" 或者 "132"
1.2 条件语句
1.2.1 概念
条件语句能够表达 "如果 ... 否则 ..." 这样的语义, 这构成了计算机中基础的 逻辑判定
条件语句 也叫做 分支语句, 表示了接下来的逻辑可能有几种走向
1.2.2 语法格式
(1) if
if expression:do_something1do_something2
next_something
# 如果 expression 值为 True, 则执行 do_something1, do_something2, next_something
# 如果 expression 值为 False, 则只执行 next_something, 不执行 do_something1, do_something2
(2) if - else
if expression:do_something1
else:do_something2
# 如果 expression 值为 True, 则执行 do_something1
# 如果 expression 值为 False, 则执行 do_something2
(3) if - elif - else
if expression1:do_something1
elif expression2:do_something2
else:do_something3
# 如果 expression1 值为 True, 则执行 do_something1
# 如果 expression1 值为 False, 并且 expression2 为 True 则执行 do_something2
# 如果 expression1 值为 False, 并且 expression2 为 False 则执行 do_something3
注: Python中的条件语句写法, 和很多其他编程语言不一样
1. if 后面的条件表达式, 没有 ( ), 使用 : 作为结尾
2. if / else 条件后要执行的 "语句块", 使用 缩进 来表示, 而不是 { }
3. 对于多条件分支, 不是写作 else if, 而是 elif
1.3 循环语句
1.3.1 while循环
Python 的 while 循环用于在条件为真时重复执行代码块。语法如下:
while 条件:循环体
# 条件为真, 则执行循环体代码
# 条件为假, 则结束循环
循环语句中也可以套用循环
1.3.2 for循环
Python的 for 循环用于遍历序列(如列表、字符串、元组等)或其他可迭代对象,语法如下:
for 变量 in 可迭代对象:循环体代码
# "可迭代对象",指的是 "内部包含多个元素, 能一个一个把元素取出来的特殊变量"
for i in range(1, 10):print(i)
print()
for i in range(2, 12, 2):print(i)
print()
for i in range(10, 0, -1):print(i)
# 使用 range 函数, 能够生成一个可迭代对象. 生成的范围为【左闭右开】,即 [1, 10)
# 通过 range 的第三个参数, 可以指定迭代时候的 "步长". 也就是一次让循环变量加几
# range 的步长也可以为负数
1.3.3 continue 和 break
continue 表示结束这次循环, 进入下次循环
break 表示结束整个循环
# continue
for i in range(1, 6):if i == 3:continueprint(i)
# 输出 1,2,4,5print()# break
for i in range(1, 6):if i == 3:breakprint(i)
# 输出1,2
2. 函数
2.1 概念
编程中的函数是一段可以被重复使用的代码片段
通过函数可以将复杂任务分解为更小的模块,提高代码的可读性和复用性。函数通常接受输入参数,执行特定操作,并返回结果
# 函数定义
def calcSum(beg,end):sum = 0for i in range(beg,end+1):sum +=1print(sum)
# 函数调用
calcSum(1,10)
calcSum(1,5)
# 通过函数,对于重复的代码做成一个函数,调用即可,消除了重复代码
2.2 语法格式
# 创建/定义函数
def 函数名(形参列表):函数体return 返回值# 调用函数
函数名(实参列表) # 不考虑返回值
返回值 = 函数名(实参列表) # 考虑返回值# 函数定义并不会执行函数体内容,必须调用才执行
# 函数必须先定义,再使用,否则会报错test() # 还没有定义, 就先执行调用了, 此时就会报错def test():print("test")
2.2.1 函数参数
2.2.1.1 形参和实参
函数参数分为 形参和实参
函数定义的时候, 可以在 ( ) 中指定 "形式参数" (简称 形参),
函数调用的时候, 由调用者把 "实际参数"(简称 实参) 传递进去
def calcSum(beg,end):sum = 0for i in range(beg,end+1):sum += i;print(sum)sum(1,100)
# beg,end 为函数的形式参数
# 1 ,100 为函数的实际参数
# 在执行sum(1, 100)时, 就相当于让beg = 1, end = 100, 然后在函数内部就可以针对 1-100 进行运算
注:
1. 一个函数可以有一个或多个形参, 也可以没有形参
2. 一个函数的形参有几个, 那么传递的实参也要传几个(保证个数要匹配)
( PS: 和 C++ / Java 不同, Python 的函数形参不必指定参数类型,即:一个函数可以支持多种不同类型参数)
2.2.1.2 参数默认值
Python 中的函数, 可以给形参指定默认值。带有默认值的参数, 可以在调用的时候不传参
def Add(x,y,debug = False):if debug:print(f"调试信息:x={x},y={y}")return x + yprint(Add(10,20))
print(Add(10,20,True))# 因为形参部分 debug=False 为参数默认值,当不指定第三个参数的时, 默认 debug 的取值即为 False
# 但要注意,【带有默认值的参数需要放到没有默认值的参数的后面】
2.2.1.3 关键字参数
调用函数时, 需要给函数指定实参. 一般默认情况下按照形参的顺序, 来依次传递实参
但是我们也可以通过 关键字参数, 调整传参的顺序, 显式指定当前实参传递给哪个形参
def Fun(x,y):print(f'x = {x}')print(f'y = {y}')Fun(10,20)
Fun(y=20,x=10)# 上面 Fun(y=20,x=10) 通过指定实参传递给形参,这样的操作为 关键字参数
2.2.2 函数返回值
如果函数是一个 "工厂", 工厂要买入原材料, 进行加工, 并生产出产品
函数的参数就是原材料, 函数的返回值就是生产出的产品
函数的返回值通过 return 语句实现,用于将结果传递回调用处。若无 return 或 return 无参数,函数默认返回 None
# 一个函数可以有多个 return 语句
# 判断是否为奇数
def isOdd(num):if num % 2 == 0:return Falseelse:return Trueresult = isOdd(10)
# 函数一执行到 return 语句, 就会立即执行结束, 回到调用位置
# 如果 num 是偶数, 则进入 if 后, 就会触发 return False , 不会继续执行 return True# 一个函数也可以没有 return 语句或 return 无参数
def Fun():print("Hello")# return
result = Fun()
print(result) # 输出: None# 一个函数可以一次返回多个返回值,通过 , 来分割多个返回值
def getP():x = 10y = 20return x,y
a, b = getP()# 如果只关注其中部分返回值, 可以使用 _ 来忽略不想要的返回值
def getP():x = 10y = 20return x,y
_, b = getP()
2.3 变量作业域
def get():x = 10y = 20return x,yx, y = get()
观察上述代码,函数内部存在 x, y, 外部也有 x, y。但是这两组 x, y 不是相同的变量, 只是恰好有一样的名字
# 在函数内部定义的 x, y 只在函数内部生效. 出了函数的范围, 这两个变量就不再生效了
def get():x = 10y = 20return x,yget()
# print(x,y) 会代码报错# 在不同的作用域中,允许存在相同变量
x = 10
def change():x = 20print(f"函数内部 x = {x}")change()
print(f'函数外部 x = {x}')
# 虽然名字相同,但 x 的作用域不同,所以是不同变量
# 在函数内部的变量, 称为 "局部变量"
# 不在任何函数内部的变量, 称为 "全局变量"# 如果函数内部尝试访问的变量在局部不存在, 就会尝试去全局作用域中查找(先局部,再全局)
x = 10
def test1():print(f"函数内部 x = {x}")
test1()# 如果是想在函数内部, 修改全局变量的值, 需要使用 global 关键字声明
x = 20
def test2():global xx = 10print(f"函数内部 x = {x}")test2()
print(f'函数外部 x = {x}')
# 如果此处没有 global, 函数内部的 x = 10 就会被视为是创建一个局部变量 x,和全局的 x 无关
对于语法结构如 if / while / for 等语块则不会影响变量的作用域
for i in range(1,2):print(f'函数内部 i = {i}')
print(f'函数外部 i = {i}')
# 在 if / while / for 中定义的变量, 在语句外面也可以正常使用
2.4 函数执行过程
2.4.1 一般调用
调用函数才执行函数体代码. 不调用则不会执行。函数体执行结束(或者遇到 return 语句), 则回到函数调用位置, 继续往下执行
def test():print("函数内")print(1)
test()
print(2)
test()
test()
print(3)
2.4.2 链式调用
把一个函数的返回值, 作为另一个函数的参数, 这种操作称为 链式调用
def isOdd(num):if num % 2 == 0:return Falseelse:return Trueprint(isOdd(10))
# 将 isOdd 函数的返回值作为 print 函数的参数,实现链式调用
2.4.3 嵌套调用
嵌套调用 指在一个函数内部调用另一个函数,形成层级关系
# 内层函数可以访问外层函数的局部变量(非全局变量)
def a():print("函数 a")def b():print("函数 b")a()def c():print("函数 c")b()def d():print("函数 d")c()d()
# d 调用 c,c 调用 b,b 调用 a,形成层级关系
函数之间的调用关系, 在 Python 中会使用一个特定的数据结构来表示, 称为 函数调用栈 . 每次函数调用,都会在调用栈里新增一个元素, 称为 栈帧
每个函数的局部变量, 都包含在自己的栈帧中
2.5 函数递归
递归是 嵌套调用 中的一种特殊情况, 即一个函数嵌套调用自己
# 计算 4 的阶乘
def factor(n):if n == 1:return 1else:return n * factor(n - 1)print(factor(4))
# 在 factor 函数内部,又调用了 factor 函数自身
递归必须满足以下条件:
1. 存在递归结束条件. 比如 if n == 1 就是结束条件. 当 n 为 1 的时候, 递归就结束了
2. 每次递归的时候, 要保证函数的实参是逐渐逼近结束条件
如果上述条件不能满足, 就会出现 "无限递归" 的错误
( 如前文, 函数调用时会在【函数调用栈】中记录每一层函数调用的信息。但是函数调用栈的空间不是无限大的.,如果调用层数太多,,就会超出栈的最大范围, 导致出现问题)
递归的优点:
1. 递归类似于 "数学归纳法" , 明确初始条件, 和递推公式, 就可以解决一系列的问题.
2. 递归代码往往代码量非常少
递归的缺点:
1. 递归代码往往难以理解, 很容易超出掌控范围
2. 递归代码容易出现栈溢出的情况
使用递归要慎重