模块化编程
模块化编程指把程序进行封装(函数封装,面向对象,文件。。。)
函数
什么是函数?
function -> 函数,功能
函数就是一个具有特定功能的代码块
函数的作用?
函数就是把代码进行封装,以提高代码的重用性,提高开发效率,并且降低了后期的维护成本
函数的定义和使用
# 定义函数【基本结构】
def 函数名([参数列表]):
当前函数的具体功能的代码
当前函数的具体功能的代码
。。。。
# 函数封装完并不会执行,只是把函数定义了而已
# 如果想使用定义的函数,那么就需要用语法来进行函数的调用
# 函数的调用
函数名()
# 函数的定义格式
def love():
print('i')
print('love')
print('you')
# 函数的调用
love()
love()
def lovess():
print(12312312)
lovess()
函数的特征及注意事项
- 函数定义后,不调用不执行
- 不能在函数定义前调用函数
- 函数的调用不受次数影响
- 函数的命名要遵守命名规范
- 字母数字下划线,不能以数字开头
- 严格区分大小写,不能使用关键字
- 命名最好有意义,且不要使用中文
- 函数名不要冲突,冲突后会被覆盖
关于函数的参数
函数在定义时,可以在参数列表的位置定义形参
如果函数有形参,那么在函数调用时也需要给定参数
实参将值传递给形参的过程,本质上就是变量赋值操作
函数参数概念及分类
函数参数:调用时需要传递的数据.
函数参数大类分为形参和实参:
. 形参意思: 函数定义时的参数
. 实参意思: 函数调用时的参数
形实关系:函数调用时,形参和实参个数需要一一对应
形参种类: 普通参数,默认参数,普通收集参数,命名关键字参数,关键字收集参数
实参种类: 普通实参,关键字实参
# 在定义函数时,在小括号内可以定义行参(形式上的参数)
def love1(w):
print(f'i love you {w}')
# 调用带有行参的函数时,需要传递参数(实参)
# love('猩猩')
# love() # TypeError: love() missing 1 required positional argument: 'w'
# 带有多个参数的函数
def love2(x,w):
print(x)
print(w)
print(f'{x} i love you {w}')
# 函数定义了几个参数,那么在调用时就必须指定按顺序进行参数的传递
love2('狗蛋','猫咪')
普通参数
(位置参数)普通的参数,接收实参传递的值
# 普通参数 就是位置参数,也叫 顺序参数,也是必须传递的参数
# def func(x,y):
# print(x,y)
# func(1,2)
默认参数:
位于普通参数后面,具有默认值的参数
语法:(x,y=2) y就是默认参数
# 比如要求有三个参数,x,y,i,至少要传递两个,
# 那么这时最后一个参数就是默认参数,但是默认参数,需要在定义行参时,指定默认值
# def func(x,y,i=100):
# print(x,y,i)
# # 调用时传递了默认的参数,那么里面使用的就是传递的实参
# func(1,2,18)
# 调用时如果没有传递默认参数,那么就会使用默认值
#(1,2)
#func()
收集参数:
专门收集在函数调用时传递的多余的实参
1.普通收集参数:专门用于收集多余的普通参数,形成一个新的元组
语法:参数前面加* 例:*args
2.关键字收集参数:用于专门收集多余关键字实参,形成一个新的字典
语法:参数前面加** 例:**kwargs
def func(a,b,*ttt,x='+'):
print(x)
if x == '+':
print('加法运算',ttt)
else:
print('减法运算',ttt)
func(1,2,'-',112,220,'zifuchuan',3723,2323)
命名关键字参数
定义时放在*号后面的参数,调用时强制必须传入指定参数名才能调用
语法:(a,*,x) x是命名关键字参数
如果函数参数中已经有了收集参数,那么收集参数后面的参数即为命名关键字参数
语法:(*args,x,y)
# def love(a,b,c=3,*args,name):
# print(a,b,c)
# print(args)
# print(name)
# # 在调用时,必须按照行参的名字进行参数的传递
# love(1,2,4,5,6,7,8,9,name="amdin")
# # love(1,2,4,5,6,7,8,9,'admin') X
# 普通函数
def love(age,name,sex):
print(name)
print(age,sex)
# love('abc')
# 在调用普通函数时,需要按照顺序进行参数的传递
# 也可以把普通函数的普通参数按照关键字参数进行传递,
love(sex='g',name="aabbcc",age=123)
形参声明的位置顺序:
普通参数 -> 默认参数 -> 收集参数 -> 命名关键字参数 -> 关键字收集参数
def func(a,b,c=1,*args,d,**kw)
a,b为普通参数,c是默认参数,args是收集参数,d是命名关键字参数,kw是关键字收集参数
极少出现五种参数同时出现的情况
def func(a,b=2,*,c,d,**kw)
a为普通参数,b是默认参数,c,d是命名关键字参数 ,kw是关键字收集参数
# kw ==> keyword
def love(a,b,c=3,*args,**kwargs):
print(a,b,c)
print(args) # 普通收集参数,会把多余的参数收集成为 元组
print(name,age)
print(kwargs) # 关键字参数收集,会把多余的关键字参数收集为 字典
love(1,2,3,112,123,name='aaa',age=222,sex='ccc',aa='aa',bb='bb',54545,454,545)
# love(a=111,b=222,c=333,123,name='a',age=20,sex=0) # X
# 注意行参声明的位置
# 普通参数,默认参数,收集参数,关键字参数,关键字收集参数
'''
极少情况下会出现上面五种行参
一般情况下: 普通参数,收集参数,关键字收集参数
'''
所有参数的摆放问题
- 实参:普通实参在前,关键字参数在后
- 形参:
- 关键字收集参数一定在最后出现
- 收集参数推荐在普通参数之后使用
- 推荐顺序:普通形参,收集参数,关键字收集参数
函数返回值
一个函数除来可以完成一定功能之外,还可以按需要返回一些内容
函数中使用 return 关键字来指定返回数据,可以返回任意类型的数据
函数的返回值,会把数据返回到调用处,可以使用变量接收,或其它处理
函数可以分为两类
1。执行过程函数: 函数体内完成一定的功能既可,没有返回值
2。具有返回值的函数: 函数体内完成一定的功能,并且返回一个结果到函数调用处
return返回值的特征
- 函数中可以使用 return 进行数据的返回
- 可以使用return 返回 任意内容或数据
- return 会把返回值,返回到函数调用出
- return 意味着函数的结束,return之后的代码不在执行
- 如果在函数中没有使用return 或者 return后面没有任何内容,那么默认返回 None
# 在一个函数中,可以返回一些内容,也可以不返回
# 没有返回值的函数,或者理解为,没有指定返回内容,默认返回类 None
# def love(a, b):
# print(f'{a} i love you {b}')
# return 123
# r = love('奥特曼','小怪兽')
# #
# None 是一个特殊的数据,表示什么都没有,空
# 如果需要在函数中指定返回内容,可以使用 return 关键字
# def love(a,b):
# res = f'{a} i love you {b}'
# # 可以在函数体内,使用return 返回任意内容
# print(1)
# return 123232
# #love('奥特曼','小怪兽')
# print(love('老鼠','猫咪'))
# r = love('狼','羊')
# print(r)
#假设有这样一个需求,定义一个函数,完成两个数的计算,并把结果输出
# def jia(n1,n2):
# res = n1+n2
# print(res)
# jia(2,5)
# # 需求改变,定义一个函数,完成两个数的计算,并把结果返回
def jia(n1,n2):
res = n1+n2
return res
print(123123123)
r = jia(2,4)
print(r)
变量作用域
作用域就是当前起作用,可用的范围区域
变量的有效范围
全局变量:在函数内外都可以使用的变量
局部变量:在函数内部可以使用的变量
局部变量
函数内定义的变量,局部变量,在函数外不能使用
全局变量
在函数内部使用 global 直接定义的变量,就是全局变量,函数内外都可以使用
在函数外定义的变量,在函数内使用 global 关键字进行声明,那么也是全局变量
globals() 获取全局数据
locals() 获取当前作用域的数据
在函数外定义的变量,函数可以访问,但是不能更改
数据类型的分类:
可变数据类型:在函数外定义的变量,在函数可以使用,
列表和字典
不可变数据类型:在函数外定义的变量,在函数内只能访问,不能使用其它操作
不光变量有作用域,函数一样也有相同的作用域
def outer():
print('this is outer function...')
# 在函数内定义的函数,称为 局部函数,函数外无法使用
def inner():
print('this is inner function...')
inner()
outer()
# inner()
nonlocal
在内函数中如何使用上一层函数中的局部变量?
在内函数中如果想使用外层函数的变量,那么需要使用 nonlocal 关键字 引用
可以引用上一层函数中定义的局部变量,但依然不能提升为全局变量
# 定义一个外层函数
def outer():
# 外函数的局部变量
num = 10
# 内函数,局部函数,在函数的内部定义的函数
def inner():
# nonlocal 关键字在局部函数中使用,
nonlocal num # 可以引用上一层函数中定义的局部变量,但依然不能提升为全局变量
num += 1
print(num)
inner()
outer()
# print(num)
关于函数的文档
def outer():
'''
这里是让你些当前函数的文档说明的。
需要说明当前函数的作用,
如果当前函数还有行参,那么也需要对行参进行一一说明
name: 这个是一个name参数,有什么作用。。。
age : 这个表示当前的一个年龄
:return: 此处说明当前函数的返回值。。。
'''
print(globals())
print(__name__) # 获取当前脚本的文件名,
print(__doc__) # 获取当前脚本的说明文档
# print(outer.__doc__) # 获取当前函数的说明文档
'''
魔术变量
__name__ ==> 当前脚本如果作为主程序,那么值是 __main__,如果是当做一个模块,在另外一个脚本中引用去使用,那么值就是当前文件的名字
__doc__ ==> 当前脚本的文档说明 在当前脚本当中的第一个 三引号注释就是当前脚本的说明文档
{
'__name__': '__main__',
'__doc__': '\n在内函数中如果想使用外层函数的变',
'__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x110444350>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': '/Users/yc/Desktop/code/8.nonlocal关键字.py',
'__cached__': None, 'outer': <function outer at 0x1104938c0>
}
'''
函数封装练习题
# 函数封装的练习题
# 打印九九乘法表,矩形
# 定义函数,打印九九乘法表
# def jiujiu(n=0):
# '''
# 当前函数的功能就是 打印 九九乘法表
# n=0; 控制 正向输出 和 反向输出 九九乘法表 ,0为正向 默认,1为反向
# '''
# if n == 0:
# rs = range(1,10)
# else:
# rs = range(9,0,-1)
# for x in rs:
# for y in range(1,x+1):
# print(f'{x}x{y}={x*y}',end=" ")
# print()
#
# jiujiu(1)
# 封装打印矩形的函数 juxing(x=10,y=10)
def juxing(n,x,y):
print('#'*x)
for i in range(1,y+1):
if n == 1:
print('#'*x)
elif n == 0:
nbsp = ' ' * (x-1)
print(f'#{nbsp}# ')
print('#'*x)
juxing(n=0,x=20,y=20)