python之函数
先通过一个简单的例子来了解一下函数的概念:
定义一个累和函数caculatenum
def caculateNum(Num):
res = 0
for i in range(1,Num+1):
res += i
return res
res = caculateNum(100)
print(res)#5050
返回值return也可以直接用来定义函数,比如
def caculateNum(Num):
return sum([i for i in range(1,Num+1)])
res = caculateNum(100)
print(res)#5050
一,必须参数和关键字参数
1.必须参数
必须参数必须以正确的顺序传入,调用的时候必须和声明的时候保持一致
如:
def f(name, age):
print('I am %s , I am %d years old'%(name,age))
f(18,'wxn')#报错
之所以会报错是因为18,wxn没有与定义参数时的必须参数类型相对应
这里就涉及到格式化输出的问题了,%s代表字符串,%d代表十进制整数
2.关键字参数
关键字参数,使用关键字参数可以允许函数调用时和声明时顺序不一致
,python 解释器能够用参数名字匹配参数值
如:
def f(name, age):
print('I am %s , I am %d years old'%(name,age))
f(age=18,name='verg')#I am verg , I am 18 years old
这里就用到了age和name这两个关键词
二,默认参数
默认参数 缺省参数没有传入,默认值会生效
def f(name,age,sex = 'male'):
print('I am %s , I am %d years old' % (name, age))
#I am lisi , I am 19 years old
#sex : male
print('sex : %s'%sex)
#I am 张三 , I am 88 years old
#sex : famale
f(name='lisi',age=19)
f('张三',88,'famale')
三,匿名函数
lambda 参数:表达式
冒号前面是参数,可以有多个,后面是表达式,只能是一个表达式
不写return,返回值就是表达式的结果
减少代码量,代码看起来有逼格
res = lambda x , y :x*y
print(res(4,5))#20
store = []
s = "淘宝"if len(store)==0 else store[0]
即如果if后面的条件满足则返回if前的的内容
否则返回store列表的第一个数值即store[0]
print(s)#淘宝
说明条件满足
下面通过举例说明lambda函数的方便之处
def cal(x,y):
if x>y:
return x*y
else:
return x/y
print(cal(3,4))#0.75
使用lambda函数:
calc = lambda x,y:x*y if x>y else x/y
print(calc(2,3))#0.666666
冒号前面是参数,后面是表达式,而且不需要返回值return,非常方便了
用sorted(列表名,key=lambda 参数:元素)的方法直接给列表排序
stus = [
{'name':'ae','age':1,},
{'name':'ga','age':2,},
{'name':'pa','age':4,},
{'name':'ba','age':9,},
{'name':'va','age':5}
]
#key值是按照哪个元素为依据进行排序
res = sorted(stus,key=lambda x:x['age'])#取age的值进行排序
print(res)
res = sorted(stus,key=lambda x:x['name'])#根据名字的首字母顺序进行排序
print(res)
四,两种传参方式
按位置传参与按关键词传参
def get_fullname(last_name,first_name):
full_name = last_name + first_name
return full_name
full_name = get_fullname('wang','xinnan')
full_name = get_fullname(first_name= 'xinnan',last_name='wang')
print(full_name)
这里需要注意按关键词传参的时候有默认值的要放在最后面
五,变长参数
*的作用:1.将参数打包成元组
def self_print(*a):#用*将参数都放置到一个元组中
print(a)#(1, 2, 3, 4, 5, 6)
print(type(a))#<class 'tuple'>元组,元组参数不可改变
self_print(1,2,3,4,5,6)
def self_print(name,*a):
print(a)#(2, 3, 4, 5, 6)
print(name)#1
self_print(1,2,3,4,5,6)
这里self_print的第一个数值1传给了参数name,剩下的2,3,4,5,6在的打包下都传给了a
2.如果参数本身就是一个元组或者列表,能在输出的时候将它拆开
如:
t = (1,2,3,4,5)
print(*t)#1 2 3 4 5 没有括号
def f(*tt):
print(tt)#(1, 2, 3, 4, 5)
f(*[1,2,3,4,5])
**的作用:1.将参数都放到字典中,注意这个参数必须有关键字
def d_self_print(**kwargs):
print(kwargs)
d_self_print(last_name = "wang",frist_name = "xinnan")#{'last_name': 'wang', 'frist_name': 'xinnan'}
形参顺序:位置参数->元组->字典
def mix(name,*t,**kwargs):#kwargs是关键字参数的意思
print(name)#wangxinnan
print(t)#('20', 'dongqin')
print(kwargs)#{'gender': '鲁班'}
mix('wangxinnan','20','dongqin',gender = '鲁班')#带关键词的应该放在最后
return 返回值
def sum_and_avg(*numbers):
total = sum(numbers)
avg_number = total/len(numbers)
return total,avg_number
sum,avg = sum_and_avg(1,2,3,4,5,6,7,8,9,10)
print("总和是%f"% sum)#总和是55.000000
print("平均值是%f"%avg)#平均值是5.500000
函数的传參问题
1.数据分为引用类型和普通类型
python中的基本数据类型都是普通类型,数,布尔型,字符串型
除了这些以外的类型都是引用类型
普通类型赋值的时候,传的是值,引用类型赋值的时候传的是地址
举个例子
l1 = [1,2,3,4,5]
l2 = l1
l2[1] = 5
print(l1)#[1, 5, 3, 4, 5]
这里的l1中的参数属于引用类型,所以l1 l2共用同一个地址,所以在更改了l2中的第二个数据后l1中的也会一起更改,所以传參的本质就是赋值操作,如果传递的是引用类型数据,则需要注意是否在函数中对其做出了修改
def power(numbers):
numbers = [x**2 for x in numbers]
return numbers
nums = [1,2,3,4,5,6,7]
print(power(nums))#[1, 4, 9, 16, 25, 36, 49]
print(nums)#[1, 2, 3, 4, 5, 6, 7]
这里的参数属于普通类型,所以原本的nums不会一起改变
def power(numbers):
numbers = list(numbers)
numbers[3] = 10
return numbers
nums = [1,2,3,4,5,6,7,8]
print(power(nums))#[1, 2, 3, 10, 5, 6, 7, 8]成功将第四个数换成了10
函数名的本质是函数的地址
def fun():
print("hello world")
f = fun
f()
用f()可直接执行函数fun()
闭包
内层函数可以访问外层函数的值,但是不能修改
内层函数访问变量时会先从自己内部查找,如果找不到就会层层向上查找
def outter():
def inner():
print("hello innner")
return inner
fo = outter()
fo()
闭包的本质是函数的嵌套函数,外层函数返回内层函数的地址
def outter():
aa= 10
def inner():#说明使用的是全局变量,最外层
nonlocal aa
aa -= 1
print(aa)
print(aa)
return inner
fo = outter()
fo()#9
fo()#8
fo()#7
fo()#6
outter()
nonlocal:让外层的关键字在这一层生效
递归:
函数自己调用自己,编写递归或循环时,一般先考虑出口(结束的条件)问题、
举个例子:阶乘
def factorial(n):
mm = 1
for num in range(1,n+1):
mm*=num
return mm
print(factorial(5))#120
def factor(n):
if n==1:
return 1
return n*factor(n-1)#是1就返回1,否则返回n*n-1
print(factor(5))#120
高阶函数
def handle(func,*param):
return func(*param)
def my_sum(*param):
sum = 0
for i in range(len(param)):
sum += param[i]
return sum
print(my_sum(1,2,3,4,6))#16
def my_mul(*param):
mul = 1
for v in param:
mul *=v
return mul
print(handle(my_mul,1,2,3,4,5))#120
func代表函数,param代表参数
常见的高阶函数
1.map
map(func,inteable)该函数会把inteable中的数据一次传递给func函数处理,最后把结果返回
inteable是指可迭代对象,可以是一个数组
[1,2,3,4,5]-->[1,4,9,16,25]
def power(x):
return x*x
result = map(power,[1,2,3,4,5,6])
for i in result:
#print(i)
print(list(result))#[1, 4, 9, 16, 25, 36]
results = map(lambda x:x*x,[1,2,3,4,5,6,7])
print(list(results))#[1, 4, 9, 16, 25, 36]
2.reduce
reduce(func,inteable)函数:累计操作,fun函数必须接收两个参数,reduce会把func的运行结果当做一个参数
from functools import reduce
l = [1,2,3,4,5]
result1 =reduce(lambda x,y:x*y,l)
print(result1)#120
3.filter
filter(func,inteable)过滤:根据函数func来过滤interable
l1 = [1,2,3,4,5,6,7,9,34]
result = list(filter(lambda x:x%2 == 1 ,l1))
print(result)#[1, 3, 5, 7, 9]
将interable中的数据传入func中,如果函数返回true,就保留该数,不然就删去
斐波那契数列
方法一:递归法
def fbnq(n):
if n == 1 or n == 2:
return 1
return fbnq(n - 1) + fbnq(n - 2)
for i in range(1, 10):
print(fbnq(i))
2.for循环的方法
def fbnq(n):
a = 0
b = 1
if n ==1:
return 1
for i in range(2,n+1):
tmp = a + b
a ,b =b,tmp
return tmp
for i in range(1,10):
print(fbnq(i))