Python基础(三)_函数和代码复用

三:函数和代码复用

(一)函数的基本使用
1.函数的定义
  • 函数是一段具有特定功能的、可重用的语句组,用函数名来表示并通过函数名进行功能调用。函数也可以看作是一段具有名字的子程序,可以在需要的地方调用执行,不需要在每个执行的地方重复编写这些语句。每次使用函数可以提供不同的参数作为输入,以实现对不同数据的处理;函数执行后,还可以反馈相应的处理结果。

    函数能够完成特定功能,对函数的使用不需要了解函数内部实现原理,只要了解函数的输入输出方式即可。严格地说,函数是一种功能抽象。

    有些函数是用户自己编写的,称为自定义函数: Python 安装包也自带了一些函数和方法,包括Python内置的函数(如absO. eval( ). Python标准库中的函数(如math库中的sqrt( )等。

    使用函数主要有两个目的:降低编程难度和代码重用。函数是一种功能抽象,利用它可以将-一个复杂的大问题分解成一系列简单的小问题,然后将小问题继续划分成更小的问题,当问题细化到足够简单时,就可以分而治之,为每个小问题编写程序,并通过函数封装,当各个小问题都解决了,大问题也就迎刃而解。这是一种自顶向下的程序设计思想。函数可以在一个程序中的多个位置使用,也可以用于多个程序,当需要修改代码时,只需要在函数中修改一次,所有调用位置的功能都更新了,这种代码重用降低了代码行数和代码维护难度。

  • python使用def保留字定义一个函数,语法格式如下:

    def <函数名>(<参数列表>):
     <函数体>
     <返回值列表>

    函数名可以是任何有效的Python标识符;

    参数列表是调用该函数时传递给它的值,可以有零个、一个或多个,当传递多个参数时各参数由逗号分隔,当没有参数时也要保留圆括号。函数定义中参数列表里面的参数是形式参数,简称为“形参”。

    函数体是函数每次被调用时执行的代码,由一行或多行语句组成。

    当需要返回值时,使用保留字return 和返回值列表,否则函数可以没有return 语句,在函数体结束位置将控制权返回给调用者。

  • 函数调用和执行的一般形式:

    <函数名>(<参数列表>)

  • 函数定义及调用举例:

    编写生日歌,最简单可以重复使用print()语句

    print("Happy birthday to you!")
    print("Happy birthday to you!")
    print("Happy birthday, dear Climb!")
    print("Happy birthday to you!")
    

    其中,第1、2、4行代码相同,假如需要将birthday改为new year,则每处都要修改。为了避免这种情况,可以用函数进行封装。上述代码中除第3行有微小不同外其余代码完全一致, 这会带来重复代码,为了能够复用语句,将代码修改为:

    def happy():
    	print("Happy birthday to you!")
    def happyN(name):
    	happy()
    	happy()
    	print("Happy birthday, dear {}!".format(name))
    	happy()
    happyN("Linda")
    print()     #换行作用
    happyN("Liming")
    

    输出

    Happy birthday to you!
    Happy birthday to you!
    Happy birthday, dear Linda!
    Happy birthday to you!
     
    Happy birthday to you!
    Happy birthday to you!
    Happy birthday, dear Liming!
    Happy birthday to you!

  • 函数的调用
    程序调用一个函数需要执行以下4个步骤。
    (1)调用程序在调用处暂停执行。

    (2)在调用时将实参复制给函数的形参。

    (3)执行函数体语句。

    (4)函数调用结束给出返回值,程序回到调用前的暂停处继续执行。

  • 生日歌程序分析

第1到第7行是函数定义,函数只有在被调用时才执行,因此,前7行代码不直接执行。程序最先执行的语句是第8行的happyN(“Linda”)。当Python执行到这行时,由于调用了happyN()函数,当前执行暂停,程序用实参"Linda"替换happyN(name)中的形参name,形参被赋值为实参的值,使用实参代替形参执行函数体内容。当函数执行完毕后,重新回到第8行,继续执行余下语句。

2.函数的返回值
  • return语句用来退出函数并将程序返回到函数被调用的位置继续执行。return语句可以同时将0个、1个、或多个函数运算后的结果返回给函数被调用处的变量。
    例如:

    def func(m,n):
    	return m*n
    s = func("hello~",2)
    print(s)
    
  • 函数也可以没有return,此时函数并不返回值,例如生日歌程序当中happy().

3.全局变量与局部变量
  • 全局变量:指在函数之外定义的变量,一般没有缩进,在程序执行全过程有效。
    局部变量:指在函数内部使用的变量,仅在函数内部有效,当函数退出时变量将不存在。

  • 注意事项:
    (1)简单数据类型变量无论是否与全局变量重名,仅在函数内部创建和使用,函数退出后变量被释放,如有全局同名变量,其值不变。

    (2)简单数据类型变量在用global保留字声明后,作为全局变量使用,函数退出后该变量保留且值被函数改变。

    (3)对于组合数据类型的全局变量,如果在函数内部没有被真实创建的同名变量,则函数内部可以直接使用并修改全局变量的值。

    (4)如果函数内部真实创建了组合数据类型变量,无论是否有同名全局变量,函数仅对局部变量进行操作,函数退出后局部变量被释放,全局变量值不变。

4.代码复用与模块化设计
  • 主要思想:
    函数是程序的一 一种抽象,它通过封装实现代码复用。可以利用函数对程序进行模块化设计。

  • 程序由一系列代码组成,如果代码是顺序但无组织的,不仅不利于阅读和理解,也很难进行升级和维护。因此,需要对代码进行抽象,形成易于理解的结构。当代编程语言从代码层面采用函数和对象两种抽象方式,分别对应面向过程和面向对象编程思想。

    函数是程序的一-种基本抽象方式,它将一系列代码组织起来通过命名供其他程序使用。函数封装的直接好处是代码复用,任何其他代码只要输入参数即可调用函数,从而避免相同功能代码在被调用处重复编写。代码复用产生了另-一个好处,当更新函数功能时,所有被调用处的功能都被更新。

    面向过程是一种以过程描述为主要方法的编程方式,该方法要求程序员列出解决问题所需要的步骤,然后用函数将这些步骤-一步一 步实现, 使用时依次建立并调用函数或编写语句即可。面向过程编程是一种基本且自然的程序设计方法,函数通过将步骤或子功能封装实现代码复用并简化程序设计难度。

    对象是程序的一种高级抽象方式,它将程序代码组织为更高级别的类。对象包括表征对象特征的属性和代表对象操作的方法。例如,汽车是一个对象,其颜色、轮胎数量、车型是属性,代表汽车的静态值:前进、后退、转弯等是方法,代表汽车的动作和行为。在程序设计中,如果 < a > 代表对象,获取其属性 < b >采用 < a > . < b >,调用其方法< c >采用< a >.< c >0。对象的方法具有程序功能性,因此采用函数形式封装。简单地,对象是程序拟解决计算问题的一个高级别抽象,它包括一组静态值(属性)和一组函数(方法)。从代码行数角度来看,对象和函数都使用了一个容易理解的抽象逻辑,但对象可以凝聚更多代码。因此,面向对象编程更适合代码规模较大,交互逻辑复杂的程序。

    面向过程和面向对象只是编程方式不同、抽象级别不同,所有面向对象编程能实现的功能采用面向过程同样能完成,两者在解决问题上不存在优劣之分,很多专业程序员仅采用面向过程方式编程。具体采用哪种方法取决于具体开发环境和要求,- .般在编写较大规模程序时采用面向对象方法,如Windows操作系统,或需要10人或更多人协同开发的程序,或带有窗口交互类的程序。Python 语言同时支持面向过程和面向对象两种编程方式,本书仅介绍但不讲解面向对象编程。

    当程序的长度在百行以上,如果不划分模块,程序的可读性非常糟糕。解决这一问题的最好方法是将一个程序分隔成短小的程序段,每-.段程序完成-一个小的功能。无论面向过程还是面向对象编程,对程序合理划分功能模块并基于模块设计程序是一一种常用方法,被称为“模块化设计”。

    模块化设计指通过函数或对象的封装功能将程序划分成主程序、子程序和子程序间关系的表达。模块化设计是使用函数和对象设计程序的思考方法,以功能块为基本单位,一-般有以下两个基本要求:

    • (1)紧耦合:尽可能合理划分功能块,功能块内部耦合紧密。

    • (2)松耦合:模块间关系尽可能简单,功能块之间耦合度低。

      耦合性指程序结构中各模块之间相互关联的程度,它取决于各模块间接口的复杂程度和调用方式。耦合性是影响软件复杂程度和设计质量的一个重要因素。紧耦合指模块或系统间关系紧密,存在较多或复杂的相互调用。紧耦合的缺点在于更新一个模块可能导致其他模块变化,复用较困难。松耦合- -般基于消息或协议实现,系统间交互简单。

    使用函数只是模块化设计的必要非充分条件,根据计算需求合理划分函数十分重要。一般来说,完成特定功能或被经常复用的一组语句应该采用函数来封装,并尽可能减少函数间参数和返回值的数量。

    有时候尽管函数和模块化设计使整个程序看上去篇幅更长,但所增加的封装代码十分有益,它们为程序带来了模块化的层次结构,使程序具有更好的可读性。

5.函数的递归:
  • 定义:
    函数作为一.种代码封装,可以被其他程序调用,当然,也可以被函数内部代码调用。这种函数定义中调用函数自身的方式称为递归。就像- - 个人站在装满镜子的房间中,看到的影像就是递归的结果。递归在数学和计算机应用上非常强大,能够非常简洁地解决重要问题。

  • 数学上有个经典的递归例子叫阶乘,阶乘通常定义如下:

    n! = n(n - 1)(n-2)···(1)

    为了实现这个程序,可以通过:一个简单的循环累积去计算阶乘。观察5!的计算,如果去掉了5,那么就剩下计算4!,推广来看,n!=n(n-1)!。 实际上,这个关系给出了另一种表达阶乘的方式:
    阶乘表达式
    这个定义说明0的阶乘按定义是1,其他数字的阶乘定义为这个数字乘以比这个数字小1数的阶乘。递归不是循环,因为每次递归都会计算比它更小数的阶乘,直到0!。0!是已知的值,被称为递归的基例。当递归到底了,就需要一个能 直接算出值的表达式。

    阶乘的例子揭示了递归的两个关键特征。

    • (1)存在一个或多个基例,基例不需要再次递归,它是确定的表达式。
    • (2)所有递归链要以一个或多个基例结尾。
       
  • 递归使用方法:
    以阶乘计算为例

    def func(n):
        if n==0:
            return 1
        else:
            return n * fact(n-1)
    num = eval(input("请输入一个正整数:"))
    print(func(num))
    

    输出

    请输入一个正整数:10
    3628800

    fact()函数在其定义内部引用了自身,形成了递归过程(如第5行)。无限制的递归将耗尽计算资源,因此,需要设计基例使得递归逐层返回。fact()函数通过if语句给出了n为0时的基例,当n==0,fact()函 数不再递归,返回数值1,如果n!=0,则通过递归返回n与n-1阶乘的乘积。

6.Python内置函数

Python解释器提供了68个内置函数,这些函数不需要引用库直接使用;
Python内置函数

7.函数库调用方式
  • 第一种引用函数库方法

import <库名>
程序课调用库中所有函数,使用库中函数格式如下:
<库名>.<函数名>(<函数参数>)

  • 第二种引用函数库方法

from <库名> import <函数名1,函数名2,函数名3···>
from <库名> import * “此处*为通配符,表示所有函数”
调用该库的函数时不再需要使用库名,直接使用如下格式
<函数名>(函数参数)

  • 两种函数库调用方式各有优点:第一种方式能够显示标明函数来源,在引用较多库时代码可读性好;第二种方式利用保留字直接引用库中函数,可以使代码更简洁,在使用一个库情况下效果会更好。
     
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值