返回值
结束当前函数
def func():
print("func is star...")
return 0
print("func is end")
后面的print(“func is end”)是得不到运行的。
返回值的类型
def func1():
print("func1")
def func2():
print("func2")
return 0
def func3():
print("func3")
return 1,"func3",[1,2,3],{"hello":"world"}
x = func1()
y = func2()
z = func3()
func1
func2
func3
None
0
(1, ‘func3’, [1, 2, 3], {‘hello’: ‘world’})
我们发现,在func3中,我们返回了一组数据,而且每个数据的类型都是不一样的,为什么python可以这样呢?在其他编程语言中,函数的返回值都之能没有或者只有一个的。
如果你看的够仔细的话就会发现,我们实际上使用一个变量来接受返回值的(当然我们也可以用多个边来接收),而打印出来的返回值是一个元组,到这里,大家是不是明白了什么呢?
是的,实际上当我们的返回值不止一个的时候,python解释器会将我们的数据打包成一个元组返回,实际上返回值也只有一个,当我们用多个变量来接回收的时候,又将元组拆分后赋值。
实际上我们在其他语言中也可以实现,不过需要自己手动打包,先申明一个结构体,然后将要返回的数据存在结构体中,返回结构体就可以了,当然,这里还需要注意使用全局变量或者动态分配内存。
参数
形参
形参,就是没有实际内存的参数,函数定义时的x,y在函数没有被调用时,是不存在的,更没有内存。
def puts(x,y): # 这里的下x,y就是形参
print(x)
print(y)
puts("hello","world")
位置参数
上面代码中,调用函数时传递的"hello","world"两个参数即是位置参数。
Traceback (most recent call last):
File "args.py", line 5, in <module>
puts("hello")
TypeError: puts() missing 1 required positional argument: 'y'
当我们只传递一个参数hello时,报的错误就是缺少位置参数。
所谓的位置参数,就是根据位置对应关系一一匹配的传参的参数。
关键字参数
def puts(x,y):
print(x)
print(y)
puts("y = 2, x = 1")
1
2
我们发现关键子参数是可以不按照位置对应关系的,而是根据关键字进行传参的。
关键字参数和位置参数混用
讲了上面两种参数,有的朋友就会好奇了,两种参数是否可以混用呢?下面我们就来看一下:
puts(1,y = 2)
1
2
我们发现,是可以的。但是:
puts(1,x = 2)
Traceback (most recent call last):
File "args.py", line 5, in <module>
puts(1,x = 2)
TypeError: puts() got multiple values for argument 'x'
还有:
puts(x = 1,2)
File "args.py", line 5
puts(x = 1,2)
^
SyntaxError: positional argument follows keyword argument
以上例子说明啊,位置参数只能放在关键字参数之前,可以对位置参数没有匹配的参数采用关键字参数匹配,但是不能先用关键字参数传参,再用位置参数,哪怕位置是正确的。
默认参数
def func(x,y=2):
print(x,y)
func(1)
func(1,3)
1 2
1 3
所谓的默认参数,就是在我们没有传实参时,给其一个缺省值;当我给y也传递了参数时,就用我们传递的参数。
可变参数
def func(x,*args):
print(x)
print(args)
func(1,2,3,4,5)
# func(1,*[2,3,4,5]) # 同上面一样
1
(2, 3, 4, 5)
这里的*args表示可变参数,可以接受n个位置参数并转为元组,注意,是位置参数,若我们传的是关键字参数则会出错。
可变关键字参数
def func(**kwargs):
print(kwargs)
func(name="sylvain",sex="m",age="22")
{'name': 'sylvain', 'sex': 'm', 'age': '22'}
可变关键字参数可以接收N个关键字参数,并将他们转化为字典。
递归函数及其特性
# 递归函数--斐波拉契数列
def fib(x):
if x == 1:
return 1
elif x == 2:
return 2
else:
return fib(x-1) + fib(x-2)
print (fib(10))
89
所谓的递归函数,就是在函数内部自己调用自己,上面就是一个典型的例子。
递归函数的特点:
1.必须有明确的结束条件;
2.每次进入更深一层的递归时,问题的规模相比上一次递归时的问题规模有所减小。
3.递归的效率不高,递归的层数过深会导致栈溢出。
高阶函数(回调函数)
高阶函数和不同函数的区别在于
讲到回调函数,首先,我们要讲一下两点:
1.函数可以接收变量为参数
2.函数即是变量,如:
def func():
print('in the func')
print(func) # 输出函数地址
综上,既然函数可以赋值给变量,而变量可以作为参数给函数,那么我们可以知道:函数可以作为参数传递给函数。
下面我们开始讲高阶函数了。所谓高阶函数,需要满足一下两个条件之一:
- 该函数的实参是函数
- 该函数的返回值是函数
下面我们来看个例子:
def func1(x):
print("x = %s" % x)
def func2(f,s):
print("callback functiong...")
f(s)
func2(func1,"hello,world!")
上面这是一个简单的实例,在创建线程时我们会遇到类似的用法,当然,这里我们用print代替了函数的内部逻辑。
内嵌函数
所谓的内嵌函数就是在函数中定义一个函数。
def test1():
print("in the test1")
def func():
print("in the func")
return func # 若不返回,内部函数为局部变量,外部无法调用
f = test1()
f()
内嵌函数的用法具体可以看装饰器的原理,下一篇会讲到。