函数、递归函数、纯函数、内置函数、匿名函数、偏函数

1、函数

如何定义一个函数

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
def method(a):
    '''
    这是一个测试方法
    :param a:
    :return:
    '''
    a=10+1
    return a

参数:

(1)必需参数:

def sumdata(a,b): #a,b 形式参数,简称形参
    return a+b



print(sumdata(34,56))   #实际参数,简称实参
print(sumdata(a=34,b=56)) #实参的完整写法,当使用完整写法时,参数的顺序可以进行调换
print(sumdata(34,b=56)) #前面用简写,后面用完整写法
print(sumdata(a=34,56)) #错误的写法:前面用完整写法,后面用简写

(2)默认参数

def sumdata(a,b,c=100):
    return a+b+c


print(sumdata(12,35,c=1))   # 48
print(sumdata(12,35))  #147

(3)可变长度参数 *args,可以传入若干个参数

def sumdata(a,*args):
    # return (a,args) #会多一层元组  (3, (4, 5))
    return (a,*args) #不会多一层元组 进行了解包  (3, 4, 5)


print(sumdata(3,4,5))

(4)关键字参数  **kwargs,它是一个字典 **kwargs也可以写任意个值,但必须成对出现,

#如果有*args的情况,它必须位于*args的后面

def fun5(a, *args, **kwargs):
    
    return (a, *args, kwargs)

print(fun5(100, 22, 33, 79, aa=98,bb=99,cc=100))  # (100, 22, 33, 79, {'aa': 98, 'bb': 99, 'cc': 100})
print(fun5(100, 22, 33, 79, **{"aa":98,"bb":99,"cc":100})) #(100, 22, 33, 79, {'aa': 98, 'bb': 99, 'cc': 100})

 

参数中传参:

传不可变对象

def ChangeInt(a):
    a = 10

b = 2
ChangeInt(b)
print(b)   # 结果是 2

传可变对象

def changeme(mylist):
    "修改传入的列表"
    mylist.append([1, 2, 3, 4])
    print("函数内取值: ", mylist)
    return


# 调用changeme函数
mylist = [10, 20, 30]
changeme(mylist)
print("函数外取值: ", mylist)

结果:

2、递归函数

递归函数就是函数在内部调用自身。

必须有一个明确的递归结束条件,称为递归出口。

注意: 递归函数一定要写终止条件,否则将产生无限递归(死循环)

递归函数实现阶乘:n! = 1 * 2 * 3 * ... * n

def fact(n):
    if n == 1:
        return 1
    return n * fact(n - 1)
print(fact(5))      # 输出结果: 120
print(fact(1))      # 输出结果: 1

递归函数实现斐波那契数列:[1,1,2,3,5,8....]

兔子繁殖问题:兔子三个月起每个月生一只小兔子,小兔子长到三个月后每个月有生一直兔子,假如兔子都不死,那么第一个月从一只小兔子到N个月后,问兔子的总数为多少?

def fib(n):
    if n==1 or n==2:
        return 1
    else:
        return fib(n-1)+fib(n-2)
print(fib(5))  #输出结果:5
print(fib(6))  #输出结果:8 

总结来说,使用递归函数的优点是逻辑简单清晰, 缺点是过深的调用会导致栈溢出(即比较占用内存空间).(python默认最大为1000次递归)

2、纯函数

一个函数的返回值只依赖于他的参数,并且在执行过程里面没副作用,这个函数就叫纯函数。

纯函数的3个原则:

  • 变量都只在函数作用域内获取,作为函数的参数传入
  • 不会产生副作用,不会改变被传入的数据或者其他数据(全局变量)
  • 相同的输入保证相同的输出

函数的副作用是指函数被调用,完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度改变了系统环境。

#函数1的返回结果为两个参数相加的结果
def func1(a,b):
    return  a+b

3、内置函数

参考https://www.runoob.com/python/python-built-in-functions.html

filter:过滤函数,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。

#过滤函数,第一个参数为函数,第二个参数为可迭代对象
res=filter(fun,[1,3,5,7,9,11,40])
print(res)   #运行结果:<filter object at 0x10d84be80>
print(list(res))  #运行结果:[7, 9, 11, 40]

map:将可迭代对象中的数据迭代出来,一个个调用函数,并将返回结果存到新的对象中

def fun(n):
    return n>5

res=map(fun,[1,3,6,8,11,20])
print(res)   #运行结果:<map object at 0x10f0b6198>
print(list(res))   #运行结果:[False, False, True, True, True, True]

zip:打包函数,用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同。

a=[1,2,3,4,5]
b=[6,7,8,9,10]
c=[1,2,3]
d=[1,2,3,4,5,6,7]
res1=zip(a,b)
res2=zip(a,c)
res3=zip(a,d)
print(res1)   #运行结果:<zip object at 0x10c9e0d08>
print(list(res1))  #运行结果:[(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
print(list(res2))  #运行结果:[(1, 1), (2, 2), (3, 3)]
print(list(res3))   #运行结果:[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]

4、匿名函数

匿名函数语法:lambda arg1,arg2,.....argn:expression

# 冒号:之前的a,b,c表示它们是这个函数的参数。
# 匿名函数不需要return来返回值,表达式本身结果就是返回值。 

#无参匿名函数
f=lambda :True
print(f())   #运行结果:True

#有参匿名函数
lambda x: x**3  #一个参数
lambda x,y,z:x+y+z  #多个参数
lambda x,y=3: x*y  #允许参数存在默认值


a = lambda *z:z #*z返回的是一个元祖
print(a('Testing1','Testing2'))  # 运行结果:('Testing1', 'Testing2')

#配合filter函数使用
f=filter(lambda x:x>5,[1,3,5,7,8,9])
print(list(f))  #运行结果:[7, 8, 9]

5、偏函数

当函数的参数个数太多,需要简化时,可以使用functools.partail创建一个新函数,这个函数可以固定住原函数的部分参数。

from functools import partial

li=[1,2,3,4,7,8,9,11]
li1=[1,2,32,41,17,18,19,11]
li2=[3,4,17,28,19,111]
li3=[4,7,2,6,71,82,91,1221]
li4=[11,21,113,14,71,38,3,0]
# f=filter(lambda x:x>5,li)
# f1=filter(lambda x:x>5,li1)
# f2=filter(lambda x:x>5,li2)
# f3=filter(lambda x:x>5,li3)
# f4=filter(lambda x:x>5,li4)
filter2=partial(filter,lambda x:x>5) # 固定参数,传入函数名和参数
f=filter2(li)
print(list(f))  # 运行结果:[7, 8, 9, 11]

posted on 2020-08-19 10:23  crystal1126  阅读(207)  评论(0编辑  收藏  举报

导航