2021-08-07

三.函数

在我们编写代码的过程中,通常会发现代码的某些操作是重复使用的,这让我们在编写代码的时候常常采取复制粘贴的模式,然而这样的模式似乎显得有些麻烦,对于学习编程的人来说会比较low,工作效率也比较低,由此,我们引入了函数和模块的概念。

函数的作用

提出什么样的问题,就要去找到对应的解决方案,要想写出高质量的代码首先要解决的就是代码重复的问题,而函数的功能就是将具有特定功能的代码块封装起来,以便于后期写代码时调用该函数来执行相应的功能,这样就减少了代码重复的可能,并且让代码看起来更加的优美

函数定义

python中的函数与数学上的一致,每个函数都有函数名,自变量和因变量,但在python中我们称自变量为函数的参数,因变量称为返回值。

在Python中,我们用关键字def来定义函数,其后接函数名,函数名后必须跟一个圆括号,括号内用来装传入的参数,最末以冒号结尾,具体示例如下:

def function_name(parameters:参数类型)->返回类型:

#注意:一般在编写函数的时候,我们会指定函数参数类型以及返回值类型,这样做的目的是增强代码的可读性

传入的参数可以没有,也可以是多个,多个参数之间用逗号隔开,并且可以指定参数的默认值。

通常情况下,我们传入的都是位置参数,在调用函数时,只需要在对应位置上传入实参即可,但在某些时候,我们希望在调用函数时调用者必须以参数名=参数值的方式传参,就需要用到 ‘*’将位置参数与命名关键字参数隔开,” * “前为位置参数,” * “ 后为命名关键字参数,实例代码如下:

​ 该函数的作用是给定一个文件名,找到该文件名的后缀名,若无后缀名,则返回空值,其中,传入的参数是文件名的字符串,‘ * '后面指定是否输出带点的后缀名

def get_suffix(filename:str,*,has_dot)->str:
    position=filename.rfind('.')
    if position <= 0:
        return ' '
    if not has_dot:
        position+=1
    return filename[position:]

print(get_suffix('sdf.ef',has_dot=True))    #  .ef


#在这个代码中,如果函数中没有指定has_hot的默认值,在调用该函数时,如果传入参数不是带关键字参数名=参数值的形式,则会报错
    
	

需要知道的是,在设计函数时,如果函数的参数个数暂时无法确定,我们可以使用可变参数*args来接收任意数量的位置参数,**keargs用来接受任意数量的关键字参数,其本质是一个字典,字典的键对应的关键字名,值对应关键字的值,如下:

def add(*args,**keargs):

示例代码:

    def calculate(*args,init_value,**kwargs):
    """
    :param fn:
    :param args:
    :param kwards:
    :return:
    """
    total=init_value
    for arg in args:
        if type(arg) in (int,float):
            total+=arg
    for value in kwargs.values():
        if type(value) in (int, float):
            total += value
    return total

	print(calculate(1,2,3,4,init_value=0,x=1,y=2,z=3))  #16
    
    #以上代码可以看出,定义了位置参数和关键字参数后,我们在调用代码时可以传入任意多的位置数和关键字参数

以上的函数,可以看到,def下有几行代码注释,这里可以解释函数的功能以及对各个参数进行说明,增加代码的可读性,方便以后的调用,在编写函数时,我们应该这样去做

当函数首行定义好之后,冒号后回车,在已经缩进格式下开始编写代码,后面的代码块均在相同的缩进下进行编写

函数主体模块编写好之后,需要有函数的返回值, 可以通过 return 来指定函数的返回值,函数的返回值可以是谋变量值,也可以是一个表达式,注意:return具有结束调用当前函数的功能,如果不加return关键字,则函数返回值是None

高阶函数

掌握基础函数概念之后,就可以进入高阶函数的概念了。函数的参数和返回值可以是任意类型的对象,这就意味着函数本身也可以作为函数的参数或返回值,这就是所谓的高阶函数

举个例子吧

当我们在编写函数的时候,可能会对多个参数做相同的运算,此时我们就会把该运算封装成一个函数,在编写一个函数时,如果需要该方法,那我们可以直接在参数列表传入这个函数的方法,具体例子如下:

def calculate(*args,init_value,fn,**kwargs):
    """
    :param fn:
    :param args:
    :param kwards:
    :return:
    """
    total=init_value
    for arg in args:
        if type(arg) in (int,float):
            total=fn(total,arg)
    for value in kwargs.values():
        if type(value) in (int, float):
            total = fn(total, value)
    return total

编写二元函数,并调用函数:

def add(x,y):
    return x+y


def mul(x,y):
    return x*y

print(calculate(11,22,33,44,init_value=0,fn=add))      #110
print(calculate(1,2,3,4,init_value=1,fn=mul))			#24

匿名函数Lambda

Lambda函数:不用使用函数定义模式来定义的一个函数,只能有一行代码,代码中的表达式的运算结果就是该函数的返回值,语法模式如下:

lambda [arg1 ,arg2,.....argn]:expression

由上述编写的二元运算函数不难看出,其编写简单,只需要一条语句就能完成,因此我们可以使用Lambda函数来实现该功能,代码如下:

print(calculate(11,22,33,44,init_value=0,fn=lambda x,y:x+y))      #110
print(calculate(1,2,3,4,init_value=1,fn=lambda x,y:x*y))			#24

不难看出,由lambda实现的函数与上述例子想相同,并且,编写的代码相对简单灵活

函数递归调用

在编写函数时,函数可以调用别的函数,也可以调用自己,函数如果直接或间接的调用自己,我们称之为递归调用,递归函数两个要点是:递归公式和递归体,,示例如下:

def fac(num: int) -> int:
    if num == 0:
        return 1
    return num * fac(num - 1)

if __name__ == '__main__':
	print(fac(5))   #120

说到这里,函数的基本概念已经基本讲完,此时我们会思考一个问题,当我们调用的函数不在同一个文件下就无法成功调用函数,下面我们就来解决这个问题

导入模块

模块是一个包含所有你定义的函数和变量的文件,后缀名是 .py 。想要在别的源文件中使用该文件里的函数模块,就必须执行 import 语句导入该函数模块

#import 模块

#导入random模块
import random

from…import 语句:是让你从某个模块导入指定的部分到当前的源文件

from modname import name1,name2,name3...nameN

以上就是导入模块的方式

总结:在编写代码的时候,我们应该注意重复代码以及关注代码的复用性,学会提取重复代码并重构函数,拥有函数和模块的概念。在编写代码的时候,注意一些细节上的问题,学会使用Lambda函数简化代码步骤

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值