声明
1)该文章整理自网上的大牛无私奉献的资料,具体引用的资料请看参考文献。
2)本文仅供本人学习记录,非商用。所以每一部分具体的参考资料并没有详细对应。如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除。
3)博主才疏学浅,文中如有不当之处,请各位指出,共同进步,谢谢。
本节学习了Python中的函数,和其他编程语言一样,函数可以最大化代码的重用率,最小化代码的冗余,同时使用函数将过程分解使得程序更具有逻辑性。
1.函数的使用
函数的定义:def 方法名(参数1,参数2,):函数体
def add(x):
return x + 10
函数的调用:函数名(实际参数)
add(1) # -->11
2.函数变量的作用域
全局变量global与局部变量local
x = 100
def my_function():
x = 50
return x
print(x)
my_function()
print(x) # 打印结果 100 100
这是由于函数内部定义的x是局部变量,外部的x是全局变量。若想在函数内部修改全局变量需要添加global
x = 100
def my_function():
global x
x = 50
print(x)
my_function()
print(x) # 打印结果 100 50
使用global声明后函数内部修改了全局变量x。
列表的全局变量与局部变量
l =['aaaa','bbb','ccc']
def my_function():
l[0] = '0'
print(l)
my_function()
print(l)
# 打印结果 ['aaaa', 'bbb', 'ccc'] ['0', 'bbb', 'ccc']
为什么列表不用声明局部变量就会被修改呢?
答:因为列表是可变类型,传递地址引用,函数内操作可能会影响原始值。如果不希望影响原始值可以将原始值复制一份将副本传入,如l.copy()。而像数值或者字符串元组这些不可变类型的数据,会不可变类型,传递副本给函数,函数内操作不影响原始值。
内置bulid-in
l = [13,2,1]
def sorted():
return 1
sorted(l) # 会报错
内置函数和变量会拥有最高的作用域,切忌使用python内置的对象作为函数名或变量名,会造成不必要的麻烦。
封装作用域enclousure
def my_function():
x = 33
def inner():
x = 20 # 封装的
inner()
print(x)
my_function()
# 打印结果 33
函数内部再嵌套函数称为封装的作用域。
想要在封装的作用域内使用外侧函数的变量需要使用nonlocal声明。如下图所示
def my_function():
x = 33
def inner():
nonlocal x
x = 20
inner()
print(x)
my_function()
# 打印结果 20
总结:
作用域分为 内置>全局>局部>封装的
内部想使用外部:gloabl声明
封装想使用内部:nonlocal声明
3.参数
参数匹配的原则
位置匹配
def func(a,b,c):
print(a,b,c)
func(1,2,3) #func已经有自带的print,所以不需要在打印print
# 打印结果 1 2 3
关键字匹配
def func(a,b,c):
print(a,b,c)
func(c=5,b=2,a=4)
# 打印结果 4 2 5
默认值:调用时可省略传值
def func(a,b=3,c=4):
print(a,b,c)
func(1)
# 打印结果 1 3 4
def func(a,b=3,c=4):
print(a,b,c)
func(1, c=5)
# 打印结果 1 3 5
args:传递任意数量的参数
有需求为打印某名学生考试成绩的平均值,假设他有两门考试,定义avg函数,计算他成绩的平均值
def avg(score1,score2):
return (score1 + score2) / 2
avg(98.0,96.0)
# 打印结果 97.0
假设他增加了一门考试,avg函数应改为传三个参数的,如果另一名学生有四门考试的话,还需要重新写一个平均值函数。
def avg(score1,score2,score3):
return (score1 + score2 + score3) / 3
avg(98.0,96.0,97.0)
# 打印结果 97.0
为了解决这样的问题,引入可接受任意数量的*args
def avg(score1,*args):
return (score1+sum(args)) / (len(args)+1)
result = avg(98.0,96.0,98.0,100.0)
print(result)
# 打印结果 98.0
score = (98.0,96.0,98.0,100.0)
print(avg(score)) # 直接传入元组会报错,需要将元组用*解包
print(avg(*score)) # 打印结果:98.0
**kwargs:传递任意指定值的参数
有需求打印员工的信息,造打印函数display_employee()打印员工的姓名,年龄,工作,可以写成如下信息
def display_employee(name,age,job):
print('name:{},age:{},job:{}'.format(name,age,job))
display('Jerry',20,'dev')
这样写需要调用时一一对应,很容易写错,并且不好扩展。
def display(**kwargs):
for k,v in kwargs.items():
print("{}:{}".format(k,v))
display(name = 'tom', age = 20, job='dev', department = 'develop')
# 打印结果
# name:tom
# age:20
# job:dev
# department:develop
d = {'name':'lili','age':20, 'job':'dev'}
display(d) # 报错,不能直接传入字典,需要将字典用**解包
display(**d) #打印结果
lambda表达式
定义
可能只使用一次的函数为了简洁可以使用lambda匿名函数
基本格式
lambda 参数1,参数2,…:函数
可以将lambda表达式用一个变量存储起来
f = lambda name:print(name)
f('Tom') # 打印结果 Tom
f2 = lambda x,y:print(x+y)
f2(3,4) # 打印结果 7
有需求对用户使用不同语言say hello 可以写成如下代码
def hello_chinese(name):
print('你好:', name)
def hello_englise(name):
print('hello:',name)
while True:
name = input('请输入您的姓名:\n')
if name == 'stop':
break
language = input('请选择语言:\n c-->中文版\n e-->英文版\n')
if language == 'c':
hello_chinese(name)
elif language == 'e':
hello_english(name)
如果此时需要加入日文版,再写一个hello_japanese函数可能比较繁琐,使用lambda表达式
def hello_chinese(name):
print('你好:', name)
def hello_english(name):
print('hello:',name)
while True:
name = input('请输入您的姓名:\n')
if name == 'stop':
break
language = input('请选择语言:\n c-->中文版\n e-->英文版\n j-->日文版 \n')
if language == 'c':
hello_chinese(name)
elif language == 'e':
hello_english(name)
elif language == 'j':
(lambda name : print('莫西莫西', name))(name)
升级版,不使用if…elif…elif 使用字典表模拟其他函数中的switch,使用了委托的思想
def hello_chinese(name):
print('你好:', name)
def hello_english(name):
print('hello:',name)
operation = {
'c':hello_chinese,
'e':hello_english,
'j':lambda name : print('莫西莫西', name)
}
while True:
name = input('请输入您的姓名:\n')
if name == 'stop':
break
language = input('请选择语言:\n c-->中文版\n e-->英文版\n j-->日文版 \n')
operation.get(language,lambda name:print("此版本不存在"))(name)
升级版 使用函数调用函数,使用委托的思想
def hello_chinese(name):
print('你好:', name)
def hello_english(name):
print('hello:',name)
def hello(action,name):
action(name)
operation = {
'c':hello_chinese,
'e':hello_english,
'j':lambda name : print('莫西莫西', name)
}
while True:
name = input('请输入您的姓名:\n')
if name == 'stop':
break
language = input('请选择语言:\n c-->中文版\n e-->英文版\n j-->日文版 \n')
hello(operation.get(language,lambda name:print("此版本不存在")),name)
map函数
功能:将一个可迭代对象都传入一个函数中进行处理
格式:map(函数,可迭代对象),map中函数可以事先定义好也可以使用lambda表达式
需求:将元素为1-20的列表中的每个数值加5存成一个新的列表
有三种方法
l = list(range(1,21))
result = []
# 1.使用for循环
for x in l:
result.append(x+5)
# 2.使用推导
result = [x+5 for x in l]
# 3.使用map函数
def add_num(x):
return x+5
result = list(map(add_num,l))
filter函数
功能:将可迭代对象都通过一个函数进行过滤
格式:filter(函数,可迭代对象) filter中函数可以事先定义好也可以使用lambda表达式
需求:将元素为1-20的列表中的偶数存成一个新的列表
有三种方法
l = list(range(1,21))
result = []
# 1.使用for循环
for x in l:
if x % 2 == 0:
result.append(x)
# 2.使用推导
result = [x for x in l if x % 2 == 0]
# 3.使用map函数
def even_num(x):
return x % 2 == 0
result = list(filter(even_num,l))
这三种方法:因推导底层使用c语言速度最快,更推荐使用推导方法。但需要更复杂的操作与过滤就需要使用map和filter。
总结
练习
3、