函数
函数是代码的一种组织形式,函数应该能完成一项特定的任务
一个函数一般完成一项特定的功能(专一性)
- 函数可以嵌套使用
- 函数的使用
- 函数使用前需要先定义
- 定义时不会自动执行
- 语法:
def function_name():
- 括号内可以有形参
- 函数内所有代码注意缩进
- 使用函数时需要调用
- 调用时函数立即执行
- 语法:
function_name()
- 括号内可以有实参
- 函数使用前需要先定义
# 函数的定义和调用
def function():
print('Hello,World.')
function()
"""
运行结果:
Hello,World.
"""
参数
参数负责给函数传递一些必要的数据或信息
- 可有可没有
- 形参(形式参数):在函数定义的时候用到的参数,没有具体值,只是一个占位符
- 实参(实际参数):在调用函数时输入的具体的值
# 形参和实参案例
def hello(person):
print('{0},你好吗?'.format(person))
print('{},祝你今天过的开心'.format(person))
p1 = '小明'
hello(p1)
p2 = '小红'
hello(p2)
"""
运行结果:
小明,你好吗?
小明,祝你今天过的开心
小红,你好吗?
小红,祝你今天过的开心
"""
参数分类
普通参数/位置参数
- 形参和实参的位置一一对应
- 形参和实参的数量必须一致
# 普通参数/位置参数案例
def normal_para(one, two, three):
print(one + two)
return None
normal_para(10, 2, 3)
normal_para(10, 2)
"""
运行结果:
12
TypeError: normal_para() missing 1 required positional argument: 'three'
"""
默认参数
- 在定义形参时需要赋默认值
- 在调用函数时实参可赋值可不赋值
- 不赋值则使用默认值
- 赋值则使用新赋的值
- 形参和实参数量不必须一致
- 形参和实参的位置一一对应
# 默认参数案例
def default_para(one, two, three=100):
print(one + two)
print(three)
return None
default_para(1, 2)
default_para(1, 2, 3)
"""
运行结果:
3
100
3
3
"""
关键字参数
- 在定义形参时可赋默认值也可不赋
- 在调用函数时传入实参格式:
形参名=值
- 形参和实参的位置不必须一一对应
- 形参和实参的数量必须一致
# 关键字参数案例
def keys_para(one, two, three):
print(one + two)
print(three)
return None
keys_para(three=30, two=2, one=1)
"""
运行结果:
3
30
"""
收集参数/可变参数
把没有位置,不能和定义时的参数位置相对应的参数,放入到一个特定的数据结构中
- 在定义形参时格式:
def func(*args)
- 在调用函数时传入实参格式:
func(p1, p2, p3)
- 收集参数和其他参数可以共存
- 访问的时候,把多余的实参放入args
- 可以把args看成一个tuple
# 收集参数案例
def stu(*args):
print(type(args))
for item in args:
print(item)
stu('Madman', 24, 'Shenzhen')
stu('Madman', 'Shenzhen')
stu()
"""
运行结果:
<class 'tuple'>
Madman
24
Shenzhen
<class 'tuple'>
Madman
Shenzhen
<class 'tuple'>
"""
# 收集参数的解包问题案例
def stu(*args):
for item in args:
print(type(item))
print(item)
print('*' * 20)
l = list()
l.append('Madman')
l.append(23)
l.append('Shenzhen')
stu(l)
stu(*l)
"""
运行结果:
<class 'list'>
['Madman', 23, 'Shenzhen']
********************
<class 'str'>
Madman
<class 'int'>
23
<class 'str'>
Shenzhen
********************
"""
关键字收集参数
把关键字参数按字典格式存入收集参数
- 在定义形参时格式:
def func(**kwargs)
- 在调用函数时传入实参格式:
func(p1=v1, p2=v2)
- 关键字收集参数和其他参数可以共存
- 访问的时候,把多余的关键字参数放入kwargs
- 可以把kwargs看成一个dict
# 关键字收集参数案例
def stu(**kwargs):
print(type(kwargs))
for k,v in kwargs.items():
print(k, '-', v)
stu(name='Madman', age=24, local='Shenzhen')
stu(name='Madman', local='Shenzhen')
stu()
"""
运行结果:
<class 'dict'>
name - Madman
age - 24
local - Shenzhen
<class 'dict'>
name - Madman
local - Shenzhen
<class 'dict'>
"""
参数混合调用的顺序问题
- 关键字参数、普通参数、收集参数可以混合使用
- 普通参数和关键字参数优先
- 定义的时候一般找普通参数、关键字参数、收集参数tuple、关键字收集参数dict
# 参数混合调用的顺序案例
def stu(name, age, *args, hobby='no', **kwargs):
if hobby == 'no':
print("hello, My name is {0}, I am {1} years old, I don't have a hobby".format(name, age))
else:
print("hello, My name is {0}, I am {1} years old, I like {2}".format(name, age, hobby))
for item in args:
print(item)
for k,v in kwargs.items():
print(k, "-", v)
print("*" * 20)
name = 'Madman'
age = 23
stu(name, age)
stu(name, age, hobby='guitar')
stu(name, age, 'args1', 'args2', hobby='guitar', key1='value1', key2='value2')
"""
运行结果:
hello, My name is Madman, I am 23 years old, I don't have a hobby
********************
hello, My name is Madman, I am 23 years old, I like guitar
********************
hello, My name is Madman, I am 23 years old, I like guitar
args1
args2
key1 - value1
key2 - value2
********************
"""
小结
- 当不确定函数里将要传递多少参数时,可以用
*args
,它可以传递任意数量的参数 - 相似的,
**kwargs
允许使用没有事先定义的参数名 - 其他参数可以和命名参数首先获得参数值然后其他的参数都传递给
*args
和**kwargs
,命名参数在列表的最前端 *args
和**kwargs
可以同时在函数中定义,但是*args
必须在**kwargs
前面
返回值
调用函数的时候返回的一个执行结果
- 可有可没有
- 当没有值返回的时候,最好使用
return None
表示函数结束 - 函数一旦执行
return
,则函数立即结束 - 如果函数没有
return
,则函数默认返回None
# 返回值案例
# 两者等价
if help(None) == help(print()):
print('help(None) == help(print())')
"""
返回结果:
help(None) == help(print())
"""
# 九九乘法表
def print_line(line_num):
# 打印一行九九乘法表
for i in range(1, line_num+1):
print(value=line_num * i, end=' ')
print()
def jiujiu():
for i in range(1, 10):
print_line(i)
jiujiu()
"""
运行结果:
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72 81
"""
函数文档
对当前函数提供相关的参考信息
- 写法
- 在函数内部开始的第一行使用三引号字符串定义符
- 一般具有特定格式
- 查看
- 使用help():
help(func)
- 使用__doc__:
func
- 使用help():
# 函数文档案例
def func():
"""
这是第一行
这是第二行
"""
print('Hello,World')
help(func)
"""
运行结果:
Help on function func in module __main__:
func()
这是第一行
这是第二行
"""
变量的作用域
变量有作用域限制
- 分类:按照作用域分类
- 全局(global):在函数外部定义
- 局部(local):在函数内部定义
- 变量的作用范围:
- 全局变量:在整个全局范围都有效
- 全局变量在局部可以使用(即函数内部可以访问函数外部定义的变量)
- 局部变量在局部范围可以使用
- 局部变量在全局范围无法使用
- LEGB原则
- L(Local):局部作用域
- E(Enclosing function locale):外部嵌套函数作用域
- G(Global module):函数定义所在模块作用域
- B(Buildin):Python内置模块的作用域
# 变量的作用域案例
a = 100
def func():
global a
a = a - 1
print(a)
return None
print(a)
func()
print(a)
"""
运行结果:
100
99
99
"""
globals()和locals()
- globals():显示系统中的全局变量
- locals():显示系统中的局部变量
# globals()和locals()案例
a = 1
b = 2
def func(x, y):
e = 100
print('local: {0}'.format(locals()))
print('globals: {0}'.format(globals()))
func(3, 4)
"""
运行结果:
local: {'x': 3, 'y': 4, 'e': 100}
globals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000182A9DF1CC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Study Codes/Python/test.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x00000182AB94C1E0>}
"""
eval()和exec()
- eval()
- 把一个字符串当做一个表达式来执行,返回字符串执行后的结果
- 格式:
eval(string_code)
- 返回值:执行结果,如果无结果返回None
- exec()
- 把一个字符串当做一个表达式来执行,但不返回结果
- 格式:
exec(string_code)
- 返回值:None
# eval()和exec()案例
print(eval('1 + 1'))
print('*' * 20)
print(eval('print("我是打印内容")'))
print('*' * 20)
print(exec('1 + 1'))
print('*' * 20)
print(exec('print("我是打印内容")'))
"""
运行结果:
2
********************
我是打印内容
None
********************
None
********************
我是打印内容
None
"""