Python学习 - 语法入门:https://blog.youkuaiyun.com/wanzijy/article/details/125287855
Python学习 - 数据类型:https://blog.youkuaiyun.com/wanzijy/article/details/125341568
Python学习 - 流程控制:https://blog.youkuaiyun.com/wanzijy/article/details/125400906
Python学习 - 运算符(操作符):https://blog.youkuaiyun.com/wanzijy/article/details/125387919
Python学习 - 列表:https://blog.youkuaiyun.com/wanzijy/article/details/125457990
Python学习 - 字典:https://blog.youkuaiyun.com/wanzijy/article/details/125567225
Python学习 -元组和集合:https://blog.youkuaiyun.com/wanzijy/article/details/125577609
Python学习 - 函数(1):https://blog.youkuaiyun.com/wanzijy/article/details/125669084
Python学习 - 函数(2):https://blog.youkuaiyun.com/wanzijy/article/details/125739981
Python学习 - 类与对象:https://blog.youkuaiyun.com/wanzijy/article/details/125826952
Python学习 - 面向对象之封装:https://blog.youkuaiyun.com/wanzijy/article/details/125902925
Python学习 - 面向对象之继承:https://blog.youkuaiyun.com/wanzijy/article/details/125963829
Python学习 - 面向对象之多态:https://blog.youkuaiyun.com/wanzijy/article/details/127140632
Python - 文件操作(1):https://blog.youkuaiyun.com/wanzijy/article/details/127099071
Python - 文件操作(2):https://blog.youkuaiyun.com/wanzijy/article/details/127150189
Python学习 - 垃圾回收、特殊方法和模块:https://blog.youkuaiyun.com/wanzijy/article/details/126202999
Python学习 - 异常处理:https://blog.youkuaiyun.com/wanzijy/article/details/126803672
1. 简介
函数也是对象
函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次的调用
函数名必须要符合标识符的规范(可以包含字母、数字、下划线,但是不能以数字开头)
创建:
def 函数名([形参1, 形参2, …, 形参n]) :
代码块
比如:print()
print是函数对象,print()调用函数
2. 参数
2.1 形参和实参
形参(形式参数):定义形参就相当于在函数内部声明了变量,但是并不赋值
实参(实际参数):如果函数定义时,指定了形参,那么在调用函数时也必须传递实参,实参将会赋值给对应的形参
函数在调用时,解析器不会检查实参的类型,实参可以传递任意类型的对象(数字,布尔值,字符串,列表…)
定义形参时,可以为形参指定默认值。如果用户传递了参数的默认值没有任何作用;如果没有传递参数,则默认值就会生效
def fn(a, b, c = 20) :
print('a = ', a) # 1
print('b = ', b) # 2
print('c = ', c) # 20
fn(1, 2)
实参的传递方式:
- 位置参数:将对应位置的实参复制给对应位置的形参。即第一个实参给第一个形参,依次类推
- 关键字参数:可以不按照形参定义的顺序去传递,而直接根据参数名去传递参数
- 两种参数传递的方式可以混合使用,但是必须将位置参数写在关键字参数的前面
def fn(a, b, c) :
print('a = ', a) # 3
print('b = ', b) # 1
print('c = ', c) # 2
fn(b = 1, a = 3, c = 2)
def fn1(a, b, c = 20) :
print('a = ', a) # 1
print('b = ', b) # 3
print('c = ', c) # 2
fn1(1, c = 2, b = 3)
在函数中,对形参进行重新赋值,不会影响其他的变量
但是,如果形参指向的是一个对象,当我们通过形参去修改对象时,会影响到所有指向该对象的变量
a = [1, 2, 3]
def fn1(a) :
a[0] = 30
print(a)
fn1(a) # [30, 2, 3]
print(a) # [30, 2, 3]
如果形参是一个对象,但是不希望在函数内部的操作影响到外部的对象,可以传递对象的一个副本
a = [1, 2, 3]
def fn1(a) :
a[0] = 30
print(a)
fn1(a.copy()) # [30, 2, 3]
fn1(a[:]) # [30, 2, 3] 切片方式
print(a) # [1, 2, 3]
2.2 不定长参数
在定义函数时,可以在形参前边加上一个 * ,这样这个形参将会获取到所有的实参,会将所有的实参保存到一个元组中(装包)
在传参时,可以不传递参数,也可以传递参数
# 任意个数字相加
def sum(*nums) :
result = 0
for num in nums :
result = result + num
print(result)
sum()
sum(1, 2, 3)
可变参数只能有一个,但是可以和其他参数配合使用
混合使用时,可变参数不是必须写在最后,但是,可变参数后的所有参数,必须以关键字的形式传递
# 任意个数字相加
def fn2(a, b, *c) :
print(a, b, c)
# 第一个参数给第一个,第二个参数给第二个,其余给可变参数
fn2(1, 2, 3, 4, 5) # 1 2 (3, 4, 5)
def fn3(a, *b, c) :
print(a, b, c)
# 第一个参数给第一个,最后一个参数给c,其余给可变参数
fn3(1, 2, 3, 4, 5, c = 5 ) # 1 (2, 3, 4, 5) 6
def fn4(*a, b, c) :
print(a, b, c)
# 后面的b和c根据关键字去传递,前面的剩下的都给a
fn4(1, 2, 3, 4, b = 5, c = 5) # (1, 2, 3, 4) 5 6
def fn5(*, a, b, c) :
print(a, b, c)
# 如果在最前直接写个*,那么后面的全部参数都要以关键字传递
fn5(a = 4, b = 5, c = 6) # 4 5 6
** 形参可以接收其他的关键字参数,它会将这些参数统一保存到一个字典中
字典的 key 就是参数的名字,字典的 value 就是参数的值
** 形参也是只能有一个,并且必须写在所有参数的最后
def fn6(**a) :
print(a)
fn6(a = 4, b = 5, c = 6) # {'a': 4, 'b': 5, 'c': 6}
def fn7(b, c, **a) :
print(a) # {'a': 4, 'e': 7, 'g': 8}
print(b) # 5
print(c) # 6
fn6(a = 4, b = 5, c = 6, e = 7, g = 8)
2.3 参数解包(拆包)
传递实参时,也可以在序列类型的参数前添加 * ,这样会自动将序列中的元素依次作为参数传递
但是序列中元素的个数必须要和形参的个数相同
也可以使用 ** 对字典进行解包,但是字典里的key要和形参的名字相同
t = (10, 20, 30)
t1 = [10, 20, 30]
t2 = {'a': 100, 'b': 200, 'c': 300}
def fn8(a, b, c) :
print(a, b, c)
fn8(*t) # 10 20 30
fn8(*t1) # 10 20 30
fn8(**t2) # 100 200 300
3. 返回值
使用 return 给函数添加返回值
如果仅仅写一个 return 或者不写 return,则相当于 return None
在函数中,return 一旦执行,后面的代码都不会执行
# 任意个数字相加
def sum(*nums) :
result = 0
for num in nums :
result = result + num
return result
return 后面可以是任意的对象,甚至可以是一个函数
# 任意个数字相加
def fn() :
def fn2() :
print('我是返回值')
return fn2()
print(fn())
4. 文档字符串(doc str)
help()
- 内置函数
- 可以查询 Python 中的函数的用法
- 语法: help(函数对象)
- 比如: help(print)
在定义函数时,可以在函数内部编写文档字符串,文档字符串是函数的说明
当我们编写了文档字符串后,就可以通过 help() 函数来查看函数的说明
直接在函数的第一行写一个字符串就是文档字符串。可以是直接用单引号或双引号,也可以是使用三引号(长字符串)
def fn(a, b, c) :
'''
:param a: 第一个参数
:param b: 第二个参数
:param c: 第三个参数
:return: 无
'''
print(a, b, c)
也可以在函数声明时添加一些描述
这些描述不会对函数造成实质性的影响
# :int 传一个整型的参数,但是并不是强制,只是一个描述
# = 'hello' 参数c的默认值是 'hello'
# -> str 返回值是字符串
def fn(a:int , b:bool, c:str = 'hello' ) -> str :
print(a, b, c)
help(fn)
5. 作用域(scope)
指的是变量生效的区域
在 Python 中,有两种作用域:
- 全局作用域
- 在程序执行时创建,在程序执行结束时销毁
- 所有函数以外的区域都是全局作用域
- 在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问
- 函数作用域
- 在函数调用时创建,在调用结束时销毁
- 函数每调用一次就会产生一个新的函数作用域
- 在函数作用域中定义的变量,都是局部变量,只能在函数内部被访问
当我们使用变量时,会优先在当前作用域中寻找该变量。如果有则使用,如果没有则继续去上一级作用域中寻找
如果找到全局作用域还没有找到变量,则会抛出异常
如果需要在函数内部修改全局变量,则需要使用 “global” 关键字
来声明变量
a = 10
def fn3() :
global a
a = 20
print(a)
fn3() # 20
6. 命名空间(namespace)
变量存储的位置,每一个变量都需要存储到指定的命名空间当中
每一个作用域都会有一个对应的命名空间
命名空间实际上就是一个字典,是一个专门用来存储变量的字典
全局命名空间,用来保存全局变量
函数命名空间,用来保存函数中的变量
loclas()
- 用来获取当前作用域的命名空间
- 如果在全局作用域中调用 locals() 则获取全局命名空间,如果在函数作用域中调用 locals() 则获取函数命名空间
- 返回的是一个字典
- 向全局的字典中添加key-value,就相当于在全局中创建了一个变量
- 向函数的字典中添加key-value,就相当于在函数中创建了一个变量
scope['c'] = 1000
print(c)
def fn() :
scope = locals()
scope['b'] = 20
print(scope)
fn()
globals()
- 可以在任意位置获取全局命名空间
- 也可以通过该函数获取的字典去操作所有的变量