1. 函数基础语法知识
# 函数:函数也是一个对象,用来保存可执行的代码并且在需要时随时调用;而对象就是内存中用来存储数据的一片内存空间
# 创建函数:def 函数名([arg1,arg2...]):
# 代码块
def func():
print('hello,cris')
print('i am function of python')
# 调用函数
func()
print(type(func)) # <class 'function'>
# 函数的形参:定义形参相当于在函数内部定义了变量,但是并没有赋值
# 函数的实参:如果函数定义了实参,那么调用该函数时就需要传递对应的实参
def func(a, b):
return a + b
result = func(1, 2)
print(result) # 3
# 函数参数详解:1. 可以为函数的形参指定默认值,如果用户传递了参数,则默认值失效;如果用户没有传递实参,那么默认值生效
# 2.实参的传递方式:位置;关键字
def func(a, b, c=10):
print(a, b, c)
# 位置传参
func(1, 2, 3) # 1 2 3
# 关键字传参
func(c=11, a=12, b=0) # 12 0 11
# 位置传参和关键字传参可以混合使用,但是位置参数必须写在关键字参数前面,否则无法区分
# func(b=12,23,11) # 报错
# 函数调用时,无法对实参进行类型检查(Python 是一种动态语言);所以实参可以传递任意数据类型
func(func, 22) # <function func at 0x000001836D1057B8> 22 10
# Python 中的值传递:实参如果指向的是可变数据类型的对象,那么函数中形参修改对象将会影响到所有指向这个对象的变量;
# 实参如果指向的是不可变数据类型,那么形参的修改将不会对实参产生任何影响(换句话说,Python和java 类似,参数传递都是值传递类型)
def func(a):
a = 'cris'
print(a)
b = 'james'
func(b)
print(b)
# 不定长函数:定义参数时,可以在一个形参前面加上*,这个形参就会获取到所有的实参,并且以元祖的形式展现,也称之为参数的装包
# 带* 号的参数只能写一个,并且可以和其他形参联合使用:例如(a,b,*c)
# 如果带* 号的形参写在中间,那么带* 号的形参后面的所有参数都必须以关键字的形式传递参数
# 如果在形参列表的开头写一个*,那么表示该函数的实参都必须以关键字的形式来传参:(*,a,b,c)
def sum(a, *b):
print(a, b, type(b))
sum(1, 2, 3) # 1 (2, 3) <class 'tuple'>
def sum(*nums):
result = 0
for i in nums:
result += i
print(result)
sum(1, 2, 3, 4) # 10
# *号形参只能接受位置参数
def func(*a):
print(a)
func(1, 2, 3) # (1, 2, 3)
# func(b=2, c=3) # 报错
# 如果使用**号形参可以接受任意个关键字传参,默认会将这些参数统一保存到字典中,字典的key 就是参数的名字,value就是参数的值。**号形参只能写一个,并且必须写在最后一个
def func(**a):
print(a)
func(b=1, c=2) # {'b': 1, 'c': 2}
# 参数的解包:传递实参时,可以在序列类型的参数前面加上*,这样就会自动将序列中的元素依次作为参数传递
def func(a, b, c):
print(a, b, c)
args = (1, 2, 3)
func(*args) # 1 2 3
# 两个** 可以对字典解包,前提是参数名和key名需要一一对应
args = {'a': 100, 'b': 200, 'c': 300}
func(**args) # 100 200 300
# 函数的返回值: return 关键字可以返回任意数据类型的对象(甚至函数),可以直接使用函数的返回值,或者使用变量来接收;
# return后面不加值或者不写return,则相当于return None;return 还可以用于结束函数
# break,continue,return 之间的区别
# fn 和 fn()的区别:一个是函数对象,一个是调用函数的结果
def sum(*nums):
result = 0
for i in nums:
result += i
return result
result = sum(1, 2, 3)
print(result) # 6
# return 后面接函数对象的特殊情况(JAVA 无法这样)
def fn1():
def fn2():
print('this is fn2')
return fn2
f = fn1()
f() # this is fn2
2. 文档字符串(Python中的函数规范)
# 文档字符串:doc string,用于定义函数的说明
# help()是Python的内置函数,可以用于查询Python中函数的用法(但是可以使用插件自动提示~)
# help(print)
# 直接在函数的第一行使用```xxx```来书写函数说明
# 如果要写的更加规范和讲究,可以参考下面的Python 写法:
# 1. 在每个参数的后面使用:数据类型 来为函数的形参做出类型要求(但是无法进行强制检查,仅仅提示)
# 2. 然后在函数声明的末尾使用 -> 数据类型 来对该函数的返回值做出类型提示
def func1(a: int, b: bool, c: str='cris') -> str:
'''
函数的作用:
参数a:
参数b:
参数c:
返回值:
'''
print(a, b, c) # 1 True cris
return str(a) + str(b) + c
help(func1) # 查看函数的说明
print(func1(1, True)) # 1Truecris
3. 函数的作用域和命名空间
# 函数变量的作用域(scope):在Python 中,变量一共有两种作用域:一种是全局作用域;一种是函数作用域
# 全局作用域:
# - 在程序执行的时候创建,程序执行结束后销毁
# - 所有函数以外的区域都是全局作用域
# - 在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问
# 函数作用域:
# - 函数作用域在函数被调用时创建,调用结束后被销毁
# - 函数没调用一次,就会创建一个新的函数作用域
# - 在函数作用域中定义的变量,就是局部变量,只能在函数内部被访问
a = 10
def fn():
print(a)
fn() # 10
# 作用域支持就近原则以及层级嵌套(由内往外)
def fn1():
a = 11
def fn2():
a = 12
print("a:", a)
fn2()
fn1() # a:12
# 如果想要在函数内部修改全局作用域的变量,需要使用 global 关键字
def fn3():
# 声明全局作用域的变量
global a
a = 'cris' # 对全局作用域的变量进行修改
print('cris=', a)
fn3() # cris= cris
print('a=', a) # a= cris
# 命令空间(namespace):命令空间指的就是变量存储的位置,每一个变量都需要存储到对应的命名空间中去
# 即每一个作用域都有其对应的命名空间:全局作用域对应的全局命名空间用来保存全局变量;函数作用域对应的局部命名空间用来保存局部变量
# 命名空间实质上就是一个字典,声明的变量都是以key-value 的形式保存到这个字典中
# locals()函数用于获取命名空间,在全局作用域调用获取的是全局命名空间;在函数作用域调用,获取的是函数的命名空间
space = locals()
print(type(space)) # <class 'dict'>
print(space['a']) # cris
# 声明变量其实就是在往命名空间添加键值对
space['b'] = 123
# print(b) # 123,不推荐使用这种方式定义变量,了解即可
# 可以通过global()在任意位置获取全局命名空间,不建议使用