如果一个函数想返回两个结果怎么办?可以用两个return去实现吗?
不可以
但是可以一个return返回两个结果,这个是python的特性,java,C++就不能这样返回,只能将返回参数封装后进行返回,C++可以使用tuple返回多个,具体百度查一下
def return_num():
return 1,2
result = return_num()
print(result) # (1,2)
注意:
- return a,b 写法,返回多个数据的时候,默认是元组类型。
- return后面可以连续列表,元组或者字典,以返回多个值。
1.函数参数
#s:str代表参数s是str类型,就是参数的声明,方便调用str的方法,但是调用函数时,传别的类型也不一定会报错,并不是强制的。
#->str代表返回类型是str
def test(s:str)->str
pass
1.1位置参数(常用)
位置参数:调用函数的时候根据函数定义的参数位置来传递参数
注意:传递和定义参数的顺序及个数必须一致
def user_info(name,age,gender):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
user_info('bull',20,'男')
1.2关键字参数
关键字参数: 函数调用,通过’键=值‘形式加以指定。可以让函数更加清晰,容易使用,同时也清楚了参数的顺序需求。
注意: 函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
def user_info(name,age,gender):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
# 调用函数
user_info('bull',age=20,gender='男') #位置参数要放在关键字参数的后面,关键字参数不要求顺
序,无所谓
user_info('bull',gender='男',age=20)
1.3缺省参数
缺省参数:缺省参数也叫默认参数,用于定义函数,为参数提供默值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
注意:函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值
def user_info(name,age,gender='男'):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
# 调用函数,使用默认参数,不传gender
user_info('bull',18)
# 调用函数,更改默认的参数值
user_info('tom',age=23,gender='男')
# 调用函数,关键字参数不区分顺序,只要在位置参数后面就可以
user_info('jack',gender='男',age=25)
1.4不定长参数
不定长参数:也可叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
- 位置参数传递
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
def user_info(*args):
print(args)
user_info('TOM') # ('TOM',)
user_info() # ()
user_info('tom',90) # ('tom', 90)
- 关键字参数传递
kwargs会被视为一个字典
def user_info(**kwargs):
print(kwargs)
# 返回的结果是{'name': 'tom', 'age': 10, 'gender': '男'}
user_info(name='tom', age=10, gender='男')
1.5强制命名参数
在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”。
def f1(*a,b,c):
print(a,b,c)
#f1(2,3,4) #会报错。由于a是可变参数,将2,3,4全部收集。造成b和c没有赋值。
f1(2,b=3,c=4)
#执行结果:(2,) 3 4
2.参数传递
函数的参数传递本质上就是:从实参到形参的赋值操作。Python中“一切皆对象”,所有的赋值操作都是“引用的赋值”。所以,Python中参数的传递都是“引用传递”,不是“值传递”。
具体操作时分为两类:
1 对“可变对象”进行“写操作”,直接作用于原对象本身。
2 对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填充这块空间。
数字是不可变对象
2.1传递可变对象的引用
传递参数是可变对象(例如:列表、字典、自定义的其他可变对象等),实际传递的还是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象。
2.2传递不可变对象的引用
传递参数是不可变对象(例如: int 、 float 、字符串、元组、布尔值),实际传递的还是对象的引用。在”赋值操作”时,由于不可变对象无法修改,系统会新创建一个对象
2.3传递不可变对象包含的子对象是可变的情况
不可变对象里面包含的子对象是可变的。如果在方法内修改了这个可变对象,那么源对象也会发生变化。
a = (10,20,[5,6])
print("a:",id(a))
def test01(m):
print("m:",id(m))
m[2][0] = 888
print(m)
print("m:",id(m))
test01(a)
print(a)
#执行结果:
#a: 41611632
#m: 41611632
#(10, 20, [888, 6])
#m: 41611632
#(10, 20, [888, 6])
3.lambda表达式
语法:lambda 参数 :表达式
注意:
lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用
lambda函数能接收任何数量的参数但只能返回一个表达式的值
示例:
add = lambda x, y: x + y
print(add(3, 5)) # 输出:8
4.内置函数
4.1 map()
map() 会根据提供的函数对指定序列做映射。
语法:
map(function,iterable,....)
参数:
function:函数
iterable:一个或多个序列
返回值:python3返回的是迭代器
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回
值的新列表。如果要转换为列表,可以使用list()来转换。
示例:计算 list1 序列中各个数字的2次方
list1 = [10,20,30,3]
result = map(lambda x:x**2,list1)
print(result) #<map object at 0x01942130> 如果想要得到列表要用list()去做处理
new_list = list(result)
print(new_list) #[100, 400, 900, 9]
4.2 reduce()
reduce( func(x,y) , lst ) 函数会对参数序列中元素进行累积。 其中 func 必须有两个参数。每次
func 计算的结果继续和序列的下一个元素做累积计算
注意:
- reduce()传入的参数 func 必须接收2个参数。
- reduce是要从 functools 里面去导包的
示例:计算 list1 序列中各个数字的累加和
from functools import reduce
list1 =[1,2,3,4,5]
result = reduce(lambda x,y:x+y,list1)
print(result) # 15
4.3filter()
filter( func , lst )函数用于过滤序列,过滤掉不符合条件的元素,返回一个filter对象。如果要转换为列
表,可以使用list()来转换。
示例:筛选出列表里面的偶数项
list1 = [1,2,3,4,5,6,7,8,9,10]
def func(x):
return x%2 == 0
result = filter(func,list1)
print(result) #<filter object at 0x02BA2130>
print(list(result)) # [2, 4, 6, 8, 10]
4.4eval()函数
功能:将字符串 str 当成有效的表达式来求值并返回计算结果
⚠️eval函数 会将字符串当做语句来执行,因此会被注入安全隐患。比如:字符串中含有删除文件的语句。那就麻烦大了。因此,使用时候,要慎重!!!
语法: eval(source[, globals[, locals]]) -> value
source :一个Python表达式或函数 compile() 返回的代码对象 1
globals :可选。必须是 dictionary 2
locals :可选。任意映射对象 3
#测试eval()函数
s = "print('abcde')"
eval(s)#把s当作代码执行,执行结果:abcde
a = 10
b = 20
c = eval("a+b")
print(c)#执行结果30
dict1 = dict(a=100,b=200)
d = eval("a+b",dict1)#表示这里的a和b是使用dict1里面的a和b,而不是全部的a和b
print(d)#执行结果:300
在函数内部,如果只是使用全局变量,则无需使用global声明,如果需要修改,则需要
5.内存分析
函数也是对象,函数名存放的是函数的地址
Python中,圆括号意味着调用函数。在没有圆括号的情况下,Python会把函数当做普通对象。
def print_star(n):
print("*"*n)
print(print_star)
print(id(print_star))
c = print_star
c(3)
代码执行 def 时,系统中会创建函数对象,并通过print_star这个变量进行引用:
执行 c=print_star 后,显然将 print_star 变量的值赋给了变量 c ,内存图变成了:
6.嵌套函数(内部函数)
嵌套函数:在函数内部定义的函数!
def outer():
print('outer running...')
def inner():
print('inner running...')
inner()
outer()
#执行结果:
#outer running...
#inner running...
inner() 就是定义在 outer() 函数内部的函数。 inner() 的定义和调用都在 outer() 函数内部
7.nonlocal关键字
nonlocal 用来在嵌套函数中,声明外层的局部变量。
#测试nonlocal、global关键字的用法
a = 100
def outer():
b = 10
def inner():
nonlocal b #声明外部函数的局部变量
print("inner b:",b)
b = 20
global a #声明全局变量
a = 1000
inner()
print("outer b:",b)
outer()
print("a:",a)
#执行结果:
#inner b:10
#outer b:20
#a:1000