Python从零开始入门 - P5 函数与模块

11. 函数

11.1 什么是函数

函数是组织好的,可重复使用的,用来实现特定功能的代码块。使用函数主要有两个目的:降低编程难度和代码重用。

  • 利用函数可以将一个复杂的大问题分解成一系列简单的小问题,当问题细化为足够简单时,更容易编程实现功能。

  • 函数可以在一个程序中多个位置使用,也可以用于多个程序,当需要修改代码时,只需要在函数中修改一次,从而降低了代码行数和代码维护难度。

11.1.1 函数的定义

Python 使用 def 关键字定义函数,后接函数名、圆括号和函数体等内容,一般格式为:

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

        <函数体>

        return <返回值列表>

(1)函数名是调用该函数的唯一标识,需要的参数和自变量必须放在圆括号中间;

(2)函数体是函数每次被调用时执行的代码,由一行或多行语句组成,紧跟冒号之后换行并缩进开始

(3)如果需要返回值,使用保留字 return 和返回值列表,但可以没有 return 语句

11.1.2 函数的调用

定义了函数之后,想要让这些代码能够执行,需要调用函数,可以通过 函数名( <参数列表> ) 的方式完成调用。

def printInfo():
    print(" ********* ")
    print("Be yourself")
    print(" ********* ")
printInfo()

""" 输出结果如下:
 ********* 
Be yourself
 ********* 
"""

11.2 函数的参数和返回值

如果我们希望函数在调用时接收数据并在执行完函数体后返回值,就需要在函数定义时定义参数和返回值。

11.2.1 函数的参数

参数列表是调用该函数时传递给它的值,可以有零个、一个或多个,当传递多个参数时各参数由逗号分隔,当没有参数时也要保留圆括号

函数定义时参数列表里面的参数是形式参数,简称为“形参”

函数调用时需要在参数列表中给出要传入函数内部的参数,通常是已定义的变量或常量,这类参数称为实际参数,简称为“实参”

一旦定义了形参,在调用函数时必须给形参赋值并实参化,否则程序将会报错,无法判断形参是什么。

def countSum(a, b):  # 此处的a,b是形参
    # 计算两个数之和的函数
    c = a + b
    return c

num1, num2 = 1, 2
result = countSum(num1, num2)       # 此处的num1和num2是实参
result2 = countSum(a=num1, b=num2)  # 为了增强可读性,也可以按照形参名称输入实参
print(result)  # 3

11.2.2 默认参数

在函数定义时如果给参数设置了默认值,调用函数时,如果没有传递参数,将会使用默认参数

注意:带有默认值的参数一定要位于参数列表的最后面,否则程序会报错。

def countSum(a, b=2):  # 给b设置了默认参数b=2,如果写成(b=2, a)将会报错
    # 计算两个数之和的函数
    c = a + b
    return c

num1 = 2
result = countSum(num1)      # 结果为4
result2 = countSum(num1, 4)  # 结果为6

11.2.3 不定长参数

在实际应用中,可能需要函数能接收多于函数定义的参数,这些参数叫做不定长参数,声明时不会命名。

函数定义时一般使用 * 号或 ** 号设置不定长参数,例如:

def <函数名>(正常参数, *args, **kwargs):

        函数体

        return <返回值列表>

这里的加了星号(*)的变量 args 会存放所有未命名的变量参数args为元组

加 ** 号的变量 kwargs 会存放命名参数,即形如key=value的参数kwargs为字典

def printInfo(name, *args, **kwargs):
    print("name={}, args={}, kwargs={}".format(name, args, kwargs))


printInfo("小明")                       # name=小明, args=(), kwargs={}
printInfo("小明", 1, "a", "b", age=18)  # name=小明, args=(1, 'a', 'b'), kwargs={'age': 18}

11.2.4 函数的返回值

函数的返回值是使用 return 语句来完成的。函数可以没有return,此时函数并不返回值,也可以用 return 返回多个值,多个值以元组类型保存。

def count(a, b):
    sum_result = a + b
    multiply_result = a * b
    return sum_result, multiply_result

print(count(2, 3))  # (5, 6)
x, y = count(2, 3)
print("sum={}, multiply={}".format(x, y))  # sum=5, multiply=6

11.3 变量的作用域

一个程序中的变量包括两类:全局变量和局部变量。

  • 局部变量:在函数内部定义的变量,作用域是函数内部,意味着它只在定义它的函数中有效,一旦函数结束,局部变量将被释放。

  • 全局变量:定义在函数外,拥有全局作用域,可以在整个程序范围内访问。

如果出现全局变量和局部变量名字相同的情况,则在函数中访问的是局部变量

n = 1  # n是一个全局变量
def count(a, b):
    c = a + b  # a,b,c均为局部变量
    n = c  # 此处的n是与全局变量n同名的局部变量,在函数中访问的是局部变量
    print(n)  # n=5
    return c

# print(c)  -> 报错,name 'c' is not defined
count(2, 3)
print(n)  # n=1,局部变量n的值发生变化不影响全局变量的值

如果想要在函数中使用全局变量,有以下两种情况:

  • 如果全局变量是不可变类型,例如数值,字符串等,需要在全局变量被使用前,使用 global 关键字显式声明该变量为全局变量;

  • 如果全局变量是可变类型,例如列表、字典等:如果是修改内部的数据直接修改即可;但如果是重新赋值,同样需要使用 global 关键字显式声明

n = 1
list1 = []
list2 = []
list3 = []


def count(a, b):
    c = a + b
    global n  # 使用global关键字将n声明为全局变量
    n = c
    print(n)  # n=5

    list1.append(n)  # 修改全局变量list1中的数据,无需global声明
    global list3     # 对全局变量list2和list3重新赋值,比较一下有无global声明的区别
    list2 = [6]      # 此处的list2重新赋值后被认为是局部变量,不影响全局变量的值
    list3 = [6]


count(2, 3)
print(n)      # n=5
print(list1)  # list1=[5]
print(list2)  # list2=[]
print(list3)  # list3=[6]

11.4 递归函数

一个函数的函数体可以调用其他函数,如果调用的函数是它本身,这个函数就被称为递归函数,将反复调用其自身。

由于递归函数一直在递推调用本身,因此递归函数必须有结束条件,否则将陷入死循环。

例如n的阶乘计算(n!=1*2*...*(n-1)*n),可以通过下面的递归函数实现:

def fact(n):
    if n == 1: # 结束条件
        return 1
    return n * fact(n - 1)

print(fact(5))  # 120

11.5 匿名函数

匿名函数就是没有名称的函数,也就是不使用 def 语句定义的函数。如果要声明匿名函数,则需要使用 lambda 关键字,匿名函数的声明格式如下所示:

lambda <参数列表>:<表达式>

该表达式的返回值是一个函数,因此从某种意义上也可以认为这个返回值就是匿名函数的名称,后续和普通函数一样,通过函数名直接调用即可。

匿名函数 lambda 函数一般用于定义简单的、能够在一行内表示的函数。

f = lambda x, y: x + y
print(type(f))  # <class 'function'>
print(f(2, 3))  # 5

匿名函数常与其他函数结合使用,例如 map 函数和 filter 函数:

  • map( )函数:会根据提供的函数对指定的序列做映射,即以参数序列中的每个元素分别调用function函数,把每次调用后返回的结果保存为map对象。

    map( )函数一般格式为:map(function, iterable)

  • filter( )函数:会对指定序列执行过滤操作,即以参数序列中的每个元素分别调用function函数,符合条件的结果保存为filter对象。

    filter( )函数一般格式为:filter(function,iterable)

myList1 = [1, 2, 3, 4, 5]
map_result = map(lambda x: x + 2, myList1)
filter_result = filter(lambda x: x > 2, myList1)
print(list(map_result))     # [3, 4, 5, 6, 7]
print(list(filter_result))  # [3, 4, 5]

12. 模块和包

12.1 模块

在 Python 中用关键字 import 在文件最开始的地方来引入某个模块,一般格式为:import 模块名

如果要导入模块中的函数,一般有以下两种情况:

  • 导入某个模块中的函数,一般格式为:from 模块名 import 函数名1,函数名2....

  • 导入某个模块中的所有函数,一般格式为:from 模块名 import *

import math
print(math.sin(math.pi / 2))  # 1.0

一般来说,Python 的模块是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和 Python 语句。

Python 提供了一个__name__属性,每个模块都有一个__name__属性,当其值为‘__main__’时,表明该模块自身在运行,否则是被引用:

if __name__ == '__main__':
    x = 2 + 3
    print(x)

12.2 包

包是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境。

简单来说,包就是文件夹,但该文件夹下必须存在 __init__.py 文件,用于标识当前文件夹是一个包,该文件的内容可以为空。

常见的包的管理格式如下所示:

package_a

├──__init__.py

├──module_a1.py

└──module_a2.py

package_b

├──__init__.py

├──module_b1.py

└──module_b2.py

main.py

如果 main.py 想要引用 package_a 包中的模块 modulea1,可以使用下列语句实现:

  • from package_a import module_a1

  • import package_a.module_a1

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习GIS的小黄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值