1.调用函数:
abs(x) #返回x的绝对值
max(x,y,z) #返回最大值
数据类型转换:
int(X)
float(X)
str(X)
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
a=abs
print(a(-5))
======================
2.定义一个函数:
def my_Function(x):
if x>0:
return x
else:
return -x
print(my_Function(-88)) #调用函数
pass
pass语句指什么也不做,先把代码执行起来再说。pass还可以用在其他语法中
def my_Function(x)
pass
返回多个值
函数可以返回多个值吗?答案是肯定的。
x, y = move(100, 100, 60, math.pi / 6)
print(x, y)
151.96152422706632 70.0
但其实这只是一种假象,Python函数返回的仍然是单一值:
r = move(100, 100, 60, math.pi / 6)
print®
(151.96152422706632, 70.0)
原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
注意:函数要是没有return值,默认return None
======================
3.函数的参数
def power(a,b): #返回a的b次方
s=1
while b>0:
s=s*a
b=b-1
return s
print(power(2,10))
当然了,如果你传入的参数是power(2)
,这样函数就缺少了参数,报错。pythone可以写默认参数,写法:
def power(a,b=10): #返回a的b次方,若是缺少参数b,默认返回a的10次方
s=1
while b>0:
s=s*a
b=b-1
return s
我们来测试一下:
默认参数的定义和使用
从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,有几点要注意:
一是必选参数在前,默认参数在后,否则Python的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
二是如何设置默认参数。
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
使用默认参数有什么好处?最大的好处是能降低调用函数的难度。
可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如一个函数是:
def enroll(name,gender='Female',age=21,city='ZheJiang'):
调用enroll('Adam', 'M', city='Tianjin')
,意思是,city参数用传进去的值,其他默认参数继续使用默认值。
默认参数很有用,但使用不当,也会掉坑里。默认参数有个最大的坑,演示如下:
def add_end(L=[]):
L.append('end')
return L
print(add_end())
print(add_end())
第一个end是对的,但第二次又执行了end就不是我们想要的效果了。它仿佛记住了list L
注意:定义默认参数要牢记一点:默认参数必须指向不变对象!
所以,代码用默认参数None就没有错了,None是一个不变的对象
为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁(线程锁),同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
======================
可变参数
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
但是调用的时候,需要先组装出一个list或tuple:
calc([1, 2, 3])
calc((1, 3, 5, 7))
如果用可变参数的话,可以这样调用:
calc(1,2,3)
calc(1,3,5,7)
代码写法需要改成可变参数:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
如果已经有了一个list,那要怎么传入呢?
nums=[1,2,3]
需要这样书写:calc(nums[0],num[1],num[2])
因为代码已经改成可变参数传入,这时候传入一个nums显然会出错
======================
关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装成一个tuple 。而关键字参数允许你传入人一个含参数名的参数,这些关键字参数在函数内部自动组装成一个dict。
def info(name,age,**other):
print(name,age,other)
dic={'city':'Zj','hobby':'sport'}
info('FJY','21',**dic)
要注意的是,参数设定为关键字参数,传入的参数也要相对应。
=====================
参数组合
我们学过了必选参数,默认参数,可变参数和自定义参数,当它们同时出现在一个函数里时,参数的顺序必须是:必选参数,默认参数,可变参数,自定义参数。比如:
def func(name,age=21,*money,**hobby):
print(name,age,money,hobby)
m=(1,2,3,4,5)
h={'hobby':'sport','hobby':'japanese'}
func('fjy',22,*m,**h)
============================
4.递归函数
在函数内部,可以调用其他函数,但一个函数在内部调用本身,这个函数就是递归函数。举个例子:计算n的阶乘
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
如果我们计算fact(5),可以根据函数定义看到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。(我感觉还是循环看的舒服…)
递归函数是通过栈这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致上溢(溢出)不信可以试试fact(100000),
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环一样,所以把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数由于return n*fact(n-1) 引入乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是把每一步的乘积传入到递归函数中:
<!-- 还没写完,下次继续。。。-- >