Python程序设计 函数

简单函数

函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。

函数的使用包含两个步骤:

  1. 定义函数 —— 封装 独立的功能

  2. 调用函数 —— 享受 封装 的成果

函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的重用

函数的定义

声明函数

  1. def :表示函数的关键字,是英文 define 的缩写

  2. 函数名:函数的名称,后续根据函数名调用函数,函数名称应该能够表达函数封装代码的功能

  3. arg : 即 argument 参数

  4. 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...

  5. 函数名称的命名应该符合标识符的命名规则

    • 可以由 字母、下划线和数字组成

    • 不能以数字开头

    • 不能与关键字重名

# 声明函数
def func():# 函数体代码# 函数体代码# 函数体代码# 函数体代码print()

def 是声明函数的关键字,必须小写

由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 get_sum

调用函数

# 调用函数
函数名();  # 通过调用函数名来执行函数体代码

调用的时候千万不要忘记添加小括号

口诀:函数不调用,自己不执行

注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。

函数的封装

函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口

简单理解:封装类似于将电脑配件整合组装到机箱中 ( 类似快递打包)

例子:封装计算1-100累加和

""" 计算1-100之间值的函数
"""# 声明函数
def get_sum():total = 0for i in range(100):total += iprint(total)# 调用函数
get_sum()

例子:利用函数 求两个数的最大值

# 利用函数 求两个数的最大值
def get_max(num1, num2):if num1 > num2:print(num1)else:print(num2)get_max(1, 3)
get_max(11, 3)

调用函数很简单的,通过 函数名() 即可完成对函数的调用

细节问题

能否将函数调用放在函数定义的上方?

  • 不能

  • 因为在使用函数名调用函数之前,必须要保证 Python 已经知道函数的存在

  • 否则控制台会提示 NameError: name 'f' is not defined (名称错误:f这个名字没有被定义)

函数的功能

有两个变量 xy ,当 x 取其变化范围中的每一个特定值时,相应地有唯一的 y 与它对应,则称 yx 的函数。记为 y = fx ),其中 x 为自变量, y 为因变量。

  1. y = kx + b 封装成一个函数,其中 k=5 , b=6 , 假设 x=5

  2. 在函数下方调用线性方程函数,打印结果

"""
# 函数在数学组的表达形式
y = f(x)
y = kx + b
"""
k = 5
b = 6# define 定义
# f 为函数名
def f(x):# 里面的内容是函数体,函数执行的代码y = k * x + b# return 函数的返回值return y

参数可变

我们定义和调用一个没有参数的函数。假设需要求当 x 分别为 56 时,f(x) 的结果相加:

x = 5def f(x):y = 5 * x + 6return yprint(f(5) + f(6))

多次调用产生不同的结果

带参数的函数有一个非常大的好处,通过修改调用函数传入的参数,从而得到不同的值。

def f(x):y = 5 * x + 6return yf(5)
f(6)
f(7)

函数的返回值

建立在之前的函数之上,如果想得到函数的计算结果,然后相加在进行输出改如何处理?例如在函数外部将函数 f 的结果加 10 再进行输出。

函数的返回值

函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。

x = 5def f():y = 5 * x + 6# return 关键字 返回一个内容return yprint(f() +y)

程序运行到所遇到的第一个return即返回(退出def块),实现函数值的返回,不会再运行第二个return。返回时可附带一个返回值,由return后面的参数指定。

return 之后函数就结束了,不会再执行后续代码

案例:

编写一个函数,求1+2+3+...+n

  1. 定义一个函数

  2. 函数接收一个参数 n

  3. 对1到n的数求和

  4. 打印和

def sum_test(n):sum  = 0for x in range(1,n+1):sum += xreturn sumprint(sum_test(10))
'''
55
'''

函数的其他形式

函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式

  1. 无参数,无返回值

  2. 无参数,有返回值

  3. 有参数,无返回值

  4. 有参数,有返回值

案例:函数复用

"""
复利公式:s = p(1 + i)^n余额宝 兴全添利宝 年化 2.5610%
假设本金(principal)10000
1、请问分别存 5年 10年 15年 20年后 本金利息共多少
2、如果利率(interest)变成 6% 分别存 5年 10年 15年 20年后 本金利息共多少
3、如果本金变成 20000,利率不变 分别存 5年 10年 15年 20年后 本金利息共多少
"""def func(p, i, n):s = p * (1 + i) ** nreturn s

函数的参数

位置参数

Python 处理参数的方式要比其他语言更加灵活。其中,最熟悉的参数类型是位置参数,传入参数的值是按照顺序依次复制过去的。下面创建一个带有位置参数的函数:

需求:

y = k * x +bkb 也不固定。

def f(x, k, b):y = k * x + bprint(y)f(5, 5, 6)

尽管这种方式很常见,但是位置参数的一个弊端是必须熟记每个位置的参数的含义。在调用函数 f() 时误把最后一个参数当作第一个参数,会得到完全不同的结果:

def f(x, k, b):print("x:{} k:{} b:{}".format(x, k, b))y = k * x + breturn(y)f(5, 5, 6)

关键字参数

为了避免位置参数带来的混乱,调用参数时可以指定对应参数的名字,甚至可以采用与函数定义不同的顺序调用:

def f(x, k, b):print("x:{} k:{} b:{}".format(x, k, b))y = k * x + breturn(y)f(x=5, k=5, b=6)

你也可以把位置参数和关键字参数混合起来。首先,实例化参数 ,然后对参数使用关键字参数的方式:

def f(x, k, b):print("x:{} k:{} b:{}".format(x, k, b))y = k * x + breturn(y)f(5, k=5, b=6)

如果同时出现两种参数形式,首先应该考虑的是位置参数。

默认参数

当调用方没有提供对应的参数值时,你可以指定默认参数值。这个听起来很普通的特性实际上特别有用,以之前的例子为例:

def f(x, k=5, b=6):print("x:{} k:{} b:{}".format(x, k, b))y = k * x + breturn yf(x=5, k=5, b=6)

不确定长度的参数

*args

收集位置参数(了解)

在不清楚传入参数是多少个

# 用 * 收集位置参数
# int * 特殊符号 有特殊的作用, 在定义函数的括号里面,用于收集所有的位置参数
# 在输出 或者是运行代码的过程中 是解包 包:元组、列表、迭代器、生成器
def print_args(*args):# * 解包的标志print('位置参数的类型:', type(args))print('位置参数的内容:', args)

无参数调用函数,则什么也不会返回:

>>> print_args()
print_args ()

给函数传入的所有参数都会以元组的形式返回输出:

>>> print_args(3, 2, 1, 'wait!', 'uh...')(3, 2, 1, 'wait!', 'uh...')

这样的技巧对于编写像 print() 一样接受可变数量的参数的函数是非常有用的。如果你函数同时有限定的位置参数,那么 *args 会收集剩下的参数:

>>> def print_args1(arg1, arg2, *args):
...     print('arg1:', arg1)
...     print('arg2:', arg2)
...     print('args:', args)
...
>>> print_args1(1,2,3,4,5,6)
arg1: 1
arg2: 2
args: (3, 4, 5, 6)

当使用 * 时不需要调用元组参数 args,不过这也是 Python 的一个常见做法。

**kwargs

收集关键字参数

使用两个星号可以将参数收集到一个字典中,参数的名字是字典的键,对应参数的值是字典的值。下面的例子定义了函数 print_kwargs(),然后打印输出它的关键字参数:

def print_kwargs(*arg, **kwargs):""" args为关键字元组  kwargs为双元关键字元组 """print('位置参数:', arg)print('关键字参数:', kwargs)

例子

案例:假设 python 中的 print 不能一次性传入多个参数使用了,让我们自己实现 print 可以传递多个参数的功能。

# 假设 print 函数突然变成了一下这个样子
def print_(arg):print(arg, sep="", end="")

要求:自己编写一个 changed_print 函数实现原本 print 的功能。

例:原本函数的功能

In [1]: print(1)
1In [2]: print(1, 2, 3, 4)
1 2 3 4In [3]: print(1, 2, 3,4, sep=',')
1,2,3,4In [4]: print(1, 2, 3,4, sep=',', end='我是结尾')
1,2,3,4我是结尾
def changed_print(*args, sep=' ', end='\n'):# print_ 只能接受一个参数for arg in args[:-1]:print_1(arg)# , 空格 #print_1(sep)print(args[-1])print_1('\n')

一等公民函数

在 Python 中,函数是一等对象。编程语言理论家把“一等对象”定义为满足下述条件的程序实体:

  • 在运行时创建

  • 能赋值给变量或数据结构中的元素

  • 能作为参数传给函数

  • 能作为函数的返回结果

在 Python 中,整数、字符串和字典都是一等对象——没什么特别的。接下来的内容将重点讨论把函数作为对象的影响和实际应用。

比如说我要将之前函数修改一个名字,使用新的函数名去调用旧的函数

def f(x):y = 5 * x + 6# return 关键字 返回一个内容return yd = fprint(d(x) +d(y))

把函数当参数传递

案例需求 f(1) + f(2) + f(3) + f(4) + f(5)

print(f(1) + f(2) + f(3) + f(4) + f(5))# 把函数当参数传递
print(f(f(1)))

设:求 f(1) + f(2) + f(3) + f(4) + f(5) + ...+f(N)

def sum_(N):total = 0for i in range(1, N + 1):total += f(N)return totalprint_(sum_(5))

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

交换变量值

需求:有变量a = 10b = 20,交换两个变量的值。

  • 方法一

借助第三变量存储数据。

# 1. 定义中间变量
c = 0# 2. 将a的数据存储到c
c = a# 3. 将b的数据20赋值到a,此时a = 20
a = b# 4. 将之前c的数据10赋值到b,此时b = 10
b = cprint(a)  # 20
print(b)  # 10
  • 方法二
a, b = 1, 2
a, b = b, a
print(a)  # 2
print(b)  # 1

例子

冒泡排序(冒泡排序)也是一种简单的简单列访问排序。它重复地走过去要排序的数,一次比较两个元素,如果他们的顺序错误让他们交换过来。走访数工作列的是重复地进行到那时已经没有再需要交换了,该算法的名字会因为越过元素会来交换慢慢地“浮”到数列的排序。

需求: 任意给定一组序列数字, 比如 [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48], 将序列从小到大排列。(不能使用python函数解决)

"""需求: 任意给定一组序列数字,比如 [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48],将序列从小到大排列。(不能使用python函数解决)
"""def bubbleSort(arr): n = len(arr) for i in range(n): for j in range(0, n - 1): if arr[j] > arr[j + 1]: arr[j], arr[j + 1] = arr[j + 1], arr[j]return arrprint(bubbleSort([3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]))
# 结果:[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

递归

递归的应用场景

递归是一种编程思想,应用场景:

  1. 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现;

  2. 在后续的算法课程中,很多算法都离不开递归,例如:快速排序。

递归的特点

  • 函数内部自己调用自己

  • 必须有出口

应用:数字累加求和

  • 代码

# 3 + 2 + 1
def sum_numbers(num):if num == 1:return 1return num + sum_numbers(num-1)sum_result = sum_numbers(3)
# 输出结果为6
print(sum_result)
  • 执行结果

lambda 表达式

lambda 的应用场景

如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda 简化。

lambda语法

lambda 参数列表 : 表达式

注意

  • lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。

  • lambda表达式能接收任何数量的参数但只能返回一个表达式的值。

快速入门

# 函数
def fn1():return 200print(fn1)
print(fn1())# lambda表达式
fn2 = lambda: 100
print(fn2)
print(fn2())

注意:直接打印lambda表达式,输出的是此lambda的内存地址

示例:计算a + b

函数实现

def add(a, b):return a + bresult = add(1, 2)
print(result)

思考:需求简单,是否代码多?

lambda实现

fn1 = lambda a, b: a + b
print(fn1(1, 2))

lambda的参数形式

无参数

fn1 = lambda: 100
print(fn1())

一个参数

fn1 = lambda a: a
print(fn1('hello world'))

默认参数

fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))

可变参数:*args

fn1 = lambda *args: args
print(fn1(10, 20, 30))

注意:这里的可变参数传入到lambda之后,返回值为元组。

可变参数:**kwargs

fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))

lambda的应用

带判断的lambda

fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))

列表数据按字典key的值排序

students = [{'name': 'TOM', 'age': 20},{'name': 'ROSE', 'age': 19},{'name': 'Jack', 'age': 22}
]# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。

体验高阶函数

在Python中,abs()函数可以完成对数字求绝对值计算。

abs(-10)  # 10

round()函数可以完成对数字的四舍五入计算。

round(1.2)  # 1
round(1.9)  # 2

需求:任意两个数字,按照指定要求整理数字后再进行求和计算。

  • 方法1

def add_num(a, b):return abs(a) + abs(b)result = add_num(-1, 2)
print(result)  # 3
  • 方法2
def sum_num(a, b, f):return f(a) + f(b)result = sum_num(-1, 2, abs)
print(result)  # 3

注意:两种方法对比之后,发现,方法2的代码会更加简洁,函数灵活性更高。

函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。

内置高阶函数

map()

map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。

需求:计算list1序列中各个数字的2次方。

list1 = [1, 2, 3, 4, 5]def func(x):return x ** 2result = map(func, list1)print(result)  # <map object at 0x0000013769653198>
print(list(result))  # [1, 4, 9, 16, 25]

zip()

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

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

a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]result = zip(a,b)  # 打包为元组的列表
# 结果:[(1, 4), (2, 5), (3, 6)]result = zip(a,c)  # 元素个数与最短的列表一致
# 结果:[(1, 4), (2, 5), (3, 6)]

reduce()

reduce() 函数会对参数序列中元素进行累积。

reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。

注意:reduce()传入的参数func必须接收2个参数。

需求:计算list1序列中各个数字的累加和。

import functoolslist1 = [1, 2, 3, 4, 5]def func(a, b):return a + bresult = functools.reduce(func, list1)print(result)  # 15

filter()

filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]def func(x):return x % 2 == 0result = filter(func, list1)print(result)  # <filter object at 0x0000017AF9DC3198>
print(list(result))  # [2, 4, 6, 8, 10]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/454608.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言之数据在内存中的存储

目录 1. 整数在内存中的存储2. 大小端字节序和字节序判断什么是大小端&#xff1f;为什么有大小端&#xff1f;练习1练习2练习3练习4练习5练习6 3. 浮点数在内存中的存储浮点数存的过程浮点数取得过程练习题解析 1. 整数在内存中的存储 在讲解操作符的时候&#xff0c;我们已经…

图片解码显示

本文主要探讨基于s5pv210实现图片解码显示项目。 项目概述&#xff1a; 硬件&#xff1a;s5pv210&#xff08;已移植uboot,kernel,busybox,已搭建tftp,已挂在ntfs&#xff09; 软件:ubuntu14(已搭建tftp,搭建ntfs) 项目功能:基于s5pv210实现对bmp,jpeg,png三种图片的解析和显示…

RK3568平台 设备模型基本框架-kobject 和kset

一.什么是设备模型 字符设备驱动通常适用于相对简单的设备&#xff0c;对于一些更复杂的功能&#xff0c;比如说电源管理和热插拔事件管理&#xff0c;使用字符设备框架可能不够灵活和高效。为了应对更复杂的设备和功能&#xff0c;Linux内核提供了设备模型。设备模型允许开发…

C# 使用 MailKit 发送邮件(附demo)

C# 使用 MailKit 发送邮件&#xff08;附demo&#xff09; 介绍安装包&#xff08;依赖&#xff09;案例简单代码属性介绍&#xff1a;MailboxAddress属性介绍&#xff1a;BodyBuilderSMTP 服务器端口SSL的案例&#xff1a;非SSL&#xff1a; 介绍一下SMTP 介绍 MailKit 是一…

vue - 指令(一)

看文章可以得到什么&#xff1f; 1.可以快速的了解并会使用vue的指令 2.可以加深你对vue指令的理解&#xff0c;知道每个指令代表什么功能​​​​​​​ 目录 什么是vue的指令&#xff1f;​​​​​​​ vue常见指令的使用 v-html v-show v-if v-else 和v-else-…

N-143基于springboot博客系统

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 前端技术&#xff1a;AdminLTEHTML 服务端技术&#xff1a;springbootmybatis-plusthymeleaf 本项目分前台和后台&#xff0c;主要有普…

VC++ 头文件中又包含其他头文件的问题

一开始代码是如下&#xff0c;当前项目中没有UIlib.h这个头文件&#xff0c;项目需要这个头文件&#xff1b; 如果新建一个UIlib.h文件&#xff0c;并把它的源代码全部拷贝进此文件中&#xff0c;这样项目中就有UIlib.h头文件&#xff0c; #include "UIlib.h" 这句不…

用握力器玩谷歌小恐龙游戏(三)

往期回顾 用握力器玩谷歌小恐龙游戏&#xff08;一&#xff09; 用握力器玩谷歌小恐龙游戏&#xff08;二&#xff09; GS-GAME-PC 前言 这次更新主要是&#xff0c;将原来的使用Wifi Mesh串口接收上位机的方法&#xff0c;改成了蓝牙直连电脑的方式&#xff0c;这种方式的…

Codeforces Round 914 (Div. 2)(D1/D2)--ST表

Codeforces Round 914 (Div. 2)(D1/D2)–ST表 D1. Set To Max (Easy Version) 题意&#xff1a; 给出长度为n的数组a和b&#xff0c;可以对a进行任意次数操作&#xff0c;操作方式为选择任意区间将区间内值全部变成该区间的最大值&#xff0c; 是否有可能使得数组a等于数组b…

操作系统笔记之内存映射

操作系统笔记之内存映射 —— 杭州 2024-02-04 code review! 文章目录 操作系统笔记之内存映射一.内存映射概念1. 文件映射到内存 (Memory-Mapped Files)2. 虚拟内存管理 (Virtual Memory Management)3. 内存映射I/O (Memory-Mapped I/O)4. 图形处理 (Graphics Processing)5.…

网站为什么要用CND?

CDN对于网站来说至关重要&#xff0c;CDN对网站的重要性主要体现在可以提升用户体验、提高网站安全性、减轻服务器负担、提高SEO排名等&#xff0c;还可以为网站节省带宽成本。因此&#xff0c;选择一个性能好、速度快的CDN是很有必要的。 CDN对于现代网站来说是不可或缺的&am…

MySQL数据库练习【一】

MySQL数据库练习【一】 一、建库建表-数据准备二、习题2.1. 查询部门编号为30的部门的员工详细信息2.2.查询从事clerk工作的员工的编号、姓名以及其部门号2.3.查询奖金多于基本工资的员工的信息、查询奖金小于基本工资的员工的信息2.4.查询奖金多于基本工资60%的员工的信息2.5.…