Python青少年简明教程:函数

2024-09-03 01:44

本文主要是介绍Python青少年简明教程:函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Python青少年简明教程:函数

在Python中,函数是一段可重用的代码块,用于执行特定的任务。函数能够接受输入参数,执行特定的操作,并返回结果。

Python提供了许多内置函数,如print()、len()、eval()等,可以直接使用。编程人员还可以自定义函数。

先看几个内置函数,然后重点介绍编程人员自定义函数。

内置函数

Python 提供了许多内置函数,这些函数可以在任何 Python 程序中直接使用,不需要额外导入。下面介绍几个常用的内置函数。

1) len()函数

语法(用法):

len(object)

其中,object 是你想要获取长度的对象。

用途:返回对象的长度(元素个数)

适用于:字符串、列表、元组、字典等

示例:

print(len("Hello"))  # 输出:5
print(len([1, 2, 3]))  # 输出:3my_string = "Hello"
print(len(my_string))  # 输出 5

2) eval()函数

语法(用法):

eval(expression, globals=None, locals=None)

其中,expression 是一个字符串,必须是有效的 Python 表达式——能计算的字符串表达式。

globals(可选):一个字典,表示全局命名空间。

locals(可选):一个字典,表示局部命名空间。

示例:

x = 1
print(eval("x + 1"))  # 输出:2
result = eval("3 + 5")
print(result)  # 输出 8# 使用字典作为命名空间的例子:
globals_dict = {"a": 5, "b": 10}
result = eval("a + b", globals_dict)
print(result)  # 输出: 15

更多的情况可参见,内置函数官方文档内置函数 — Python 3.12.5 文档

下面介绍程序员自定义函数。

函数定义

编程人员还可以自定义函数。

使用 def 关键字定义函数,后跟函数名和括号(包含参数列表)。语法:

def函数名(参数列表):

    # 函数体

    return返回值

函数名:函数名可以是任何有效的标识符,但最好是有意义的名字,能反映出函数的功能。

参数列表:在圆括号中定义,用于接收传递给函数的值。多个参数用逗号分隔。参数是可选的,如果没有参数,圆括号内为空。

函数体:包含函数执行的操作或计算。

返回值:使用 return 语句返回结果给调用者。如果没有 return 语句,函数将返回 None。

函数调用

使用函数名后跟一对括号,括号中包含参数——如果有的话。

形参(形式参数,parameters)和实参(实际参数,arguments)

形参是指函数定义中使用的参数,它们相当于占位符,用于指定函数可以接受的输入。形参在函数定义时出现,用于接收函数调用时传入的实参。

实参是指在函数调用时传递给函数的具体值。实参在函数调用时出现,用于替换形参的值。

示例:

#定义add函数
def add(x, y):  
return x + y  result = add(5, 3)  # 调用函数,并接收返回值  
print(result)  # 输出:8

文档字符串

如果三重引号用放在函数、类或模块的开头,Python 会把它们当作文档字符串(docstring),这是一种特别的多行注释形式,用于生成文档,可以通过 __doc__ 属性 或 help(add) 函数查看。

def add(a, b):"""返回两个数的和。参数:a -- 第一个数b -- 第二个数"""return a + bprint(add.__doc__)  # 打印函数的文档字符串

在这个例子中,你可以通过 add.__doc__ 或 help(add) 来查看这个文档字符串的内容。

参数传递的内部机制

官方术语,参数传递使用按值调用(call by value)的方式(其中的值始终是对象的引用,而不是对象的值)。实际上,Python函数参数传递的始终对象的引用,而不是对象的值。这方面的内容,因一些人和资料介绍的比较混乱,特地附注。

【附注(有关官方文档节选):

The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, or calls itself recursively, a new local symbol table is created for that call.

https://docs.python.org/3/tutorial/controlflow.html#defining-functions

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用 按值调用 来传递的(其中的 值 始终是对象的 引用 而不是对象的值)。 [1] 当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。

https://docs.python.org/zh-cn/3/tutorial/controlflow.html#defining-functions

Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and so no call-by-reference per se.

https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

请记住,Python 中的实参是通过赋值传递的。由于赋值只是创建了对象的引用,所以调用方和被调用方的参数名都不存在别名,本质上也就不存在按引用调用的方式。

https://docs.python.org/zh-cn/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference】

这种机制有时也被一些人非正式称呼较多如“传递对象引用”(pass by object reference)、按对象引用调用(call by object reference),但机制本质不变。

对于不可变对象(如整数、字符串、元组),因为其不可变性,函数内对参数的任何修改不会影响到外部变量。对于可变对象(如列表、字典、集合),函数内对参数的修改会影响到外部变量。

a)如果传入的参数是不可变类型(如数字、字符串、元组),那么在函数体内修改参数的值,并不会影响到原来的变量。因为不可变类型的变量实际上是值的引用,当试图改变变量的值时,相当于是在创建新的对象。例如:

def change_number(num):num = 100x = 10
change_number(x)
print(x)  # 输出:10

在上面的例子中,尽管在函数内部num的值被改变了,但是原变量x的值并没有改变。参见下图:

b)如果传入的参数是可变类型(如列表、字典),那么在函数体内修改参数的值,会影响到原来的变量。因为可变类型的变量存储的是一个地址,当试图改变变量的值时,实际上是在改变这个地址所指向的内容。例如:

def change_list(lst):lst.append(100)x = [1, 2, 3]
change_list(x)
print(x)  # 输出:[1, 2, 3, 100]

在上面的例子中,函数内部对参数lst的修改影响到了原变量x的值。参见下图:

从内存管理的角度来看,Python中的变量和参数传递有一些特点

☆ 变量是对象的引用:在Python中,变量实际上是对象的引用,而不是对象本身。当你给一个变量赋值时,实际上是将变量指向了一个对象。这意味着变量可以指向不同类型的对象,并且可以在程序中随时改变指向的对象。

☆ 引用计数:Python使用引用计数来管理内存。每个对象都有一个引用计数,表示有多少个变量引用了该对象。当引用计数为0时,对象将被自动回收。当一个变量不再引用一个对象时,引用计数会减少。当引用计数为0时,对象的内存将被释放。

☆ 对象的可变性:Python中的对象分为可变对象和不可变对象。可变对象(如列表、字典)的值可以被修改,而不可变对象(如整数、字符串、元组)的值不能被修改。这意味着如果你修改了一个可变对象,那么所有引用这个对象的变量都会受到影响。

☆ 参数传递方式:在Python中,函数的参数传递是按值调用(call by value) 来传递的(其中的 值 始终是对象的 引用 而不是对象的值)——实际上,按对象引用调用(call by object reference)调用这种说法更好。对于不可变对象(如整数、字符串、元组),由于它们的值不能被改变,所以函数内部对这些对象的修改实际上是创建了一个新的对象。因此,函数内部的修改不会影响到函数外部的实际参数。对于可变对象(如列表、字典),由于它们的值可以被改变,所以函数内部对这些对象的修改会直接改变原始对象的值。因此,函数内部的修改会影响到函数外部的实际参数。

【附、Python语言的变量和参数传递情况https://blog.csdn.net/cnds123/article/details/134159800

多种(C++、Java、JavaScript、Python)编程语言参数传递方式介绍https://blog.csdn.net/cnds123/article/details/132981086 】

参数情况说明

☆位置参数(Positional Arguments)

位置参数是最基本的参数传递方式,按照参数在函数定义中的位置传递。例如:

def add(a, b):return a + bresult = add(3, 5)  # 位置参数,3 传给 a,5 传给 b
print(result)  # 输出 8

☆关键字参数(Keyword Arguments)

关键字参数通过参数名传递,可以不按照定义时的顺序传递。例如:

def greet(name, msg):print(f"{msg}, {name}!")greet(name="Alice", msg="Hello")  # 关键字参数
greet(msg="Hi", name="Bob")  # 顺序可以不同

☆默认参数(Default Arguments)

默认参数在函数定义时指定了默认值,如果调用函数时没有提供该参数,则使用默认值。例如:

def greet(name, msg="Hello"):print(f"{msg}, {name}!")greet("Alice")  # 使用默认参数,输出 "Hello, Alice!"
greet("Bob", "Hi")  # 覆盖默认参数,输出 "Hi, Bob!"

☆可变参数(Variable-length Arguments)

Python 支持可变数量的参数,使用 *args 和 **kwargs。

1) *args 用于传递任意数量的位置参数,接收的是一个元组。例如:

def print_numbers(*args):for num in args:print(num)print_numbers(1, 2, 3, 4)  # 输出 1 2 3 4

2)不定长关键字参数(**kwargs)

**kwargs 用于传递任意数量的关键字参数,接收的是一个字典。例如:

def print_info(**kwargs):for key, value in kwargs.items():print(f"{key}: {value}")print_info(name="Alice", age=25)  # 输出 "name: Alice" "age: 25"

☆在 Python 3.8 及以后的版本中,函数参数传递机制中引入了两个新的语法元素:/ 和 *,它们用来指定参数的类型,即位置参数、关键字参数以及两者混合的参数。

1)仅限位置参数(Positional-only Parameters)

使用 / 将参数标记为仅限位置参数。这意味着这些参数必须通过位置进行传递,不能使用关键字来传递。例如:

def func(a, b, /, c, d):print(a, b, c, d)func(1, 2, 3, 4)  # 正确
func(1, 2, c=3, d=4)  # 错误,会引发 TypeError

在这个例子中,a 和 b 必须通过位置传递,而 c 和 d 可以通过位置或关键字传递。

2)仅限关键字参数(Keyword-only Parameters)

使用 * 将参数标记为仅限关键字参数。这意味着这些参数必须通过关键字传递。例如:

def func(a, b, *, c, d):print(a, b, c, d)func(1, 2, c=3, d=4)  # 正确
func(1, 2, 3, 4)  # 错误,会引发 TypeError

在这个例子中,c 和 d 必须通过关键字传递,而 a 和 b 可以通过位置或关键字传递。

3)同时使用 / 和 *

在函数定义中可以同时使用 / 和 *,以指定不同类型的参数。例如:

def func(a, b, /, c, *, d):print(a, b, c, d)func(1, 2, 3, d=4)  # 正确
func(1, 2, c=3, d=4)  # 正确
func(1, 2, 3, 4)  # 错误,会引发 TypeError
func(a=1, b=2, c=3, d=4)  # 错误,会引发 TypeError

在这个例子中,a 和 b 必须通过位置传递,c 可以通过位置或关键字传递,d 必须通过关键字传递。

☆参数解包

Python 支持参数解包(unpacking),这是一种将容器(如列表、元组或字典)中的元素解包并传递给函数参数的方式。参数解包可以通过 * 和 ** 实现。

1)使用 * 解包列表或元组

当你有一个包含多个元素的列表或元组,并且你希望将这些元素作为单独的参数传递给函数时,可以使用 * 进行解包。例如:

def add(a, b, c):return a + b + cnumbers = [1, 2, 3]
result = add(*numbers)  # 等同于 add(1, 2, 3)
print(result)  # 输出 6values = (4, 5, 6)
result = add(*values)  # 等同于 add(4, 5, 6)
print(result)  # 输出 15

2) 使用 ** 解包字典

当你有一个字典,并且字典的键与函数参数名匹配时,可以使用 ** 进行解包,将字典中的键值对作为关键字参数传递给函数。例如:

def greet(name, greeting, punctuation):print(f"{greeting}, {name}{punctuation}")params = {'name': 'Alice', 'greeting': 'Hello', 'punctuation': '!'}
greet(**params)  # 等同于 greet(name='Alice', greeting='Hello', punctuation='!')

变量作用域(scope

Python 中的作用域(scope)是指变量的可访问范围。Python 主要有以下几种作用域:

☆全局作用域(Global)

全局变量在函数外部定义,全局作用域是在整个程序(模块或脚本文件)中都可以访问的变量。例如:

global_var = "I'm global"def access_global():print(global_var)access_global()  # 输出: I'm global
print(global_var)  # 输出: I'm global

☆局部作用域(Local)

局部作用域指的是在函数内部定义的变量,只在函数内部可见。例如:

def local_scope_example():x = "local"print(x)local_scope_example()  # 输出: local
# print(x)  # 这会引发 NameError,因为 x 只在函数内部定义

☆闭包函数外的函数中(Enclosing)

这指的是嵌套函数中外层函数的作用域。例如:

def outer_function():x = "outer"def inner_function():print(x)  # 可以访问外层函数的变量inner_function()outer_function()  # 输出: outer

☆内置作用域(Built-in)

这是 Python 内置的名字空间,包含了内置函数和异常名称。例如:

print(len("Python"))  # 使用内置函数 len(),输出: 6

变量查找顺序

Python 按照 LEGB规则顺序查找变量:Local → Enclosing → Global → Built-in。

例如:

x = "global"def outer():x = "outer"def inner():x = "inner"print("inner:", x)inner()print("outer:", x)outer()
print("global:", x)# 输出:
# inner: inner
# outer: outer
# global: global

特别提示:

1) global 关键字

如果你想在函数内部修改全局变量,需要使用 global 关键字。例如:

count = 0def increment():global countcount += 1print(count)increment()  # 输出: 1
increment()  # 输出: 2

2) nonlocal 关键字

在嵌套函数中,如果要修改外层函数的变量,需要使用 nonlocal 关键字。例如:

def outer():x = 0def inner():nonlocal xx += 1print(x)return innercounter = outer()
counter()  # 输出: 1
counter()  # 输出: 2

理解 Python 的作用域规则对于编写清晰、可维护的代码非常重要。它可以帮助你避免命名冲突,更好地组织代码结构,并理解变量在不同上下文中的行为。

递归函数

函数调用自身的函数。需要有基本情况来结束递归。

递归是一种强大的编程技术,它允许函数调用自身来解决问题。

递归的基本概念:

递归函数是在其定义中直接或间接调用自身的函数。它通常用于解决可以被分解成相似的子问题的问题。

递归函数的结构:

一个典型的递归函数包含两个主要部分:

基本情况(Base case):不再递归调用的条件,用于终止递归。

递归情况(Recursive case):函数调用自身的部分。

示例1 - 计算阶乘

阶乘是最经典的递归函数之一。数学上,n 的阶乘(n!)定义为:

0! = 1

n! = n * (n-1)!,当n > 0时

源码如下:

def factorial(n):# 基准情况:当 n 为 0 时,返回 1if n == 0:return 1# 递归情况:n * (n-1) 的阶乘else:return n * factorial(n - 1)print(factorial(5))  # 输出: 120

解释:

factorial(0) 返回 1(基准情况)。

factorial(n) 对于 n > 0,会递归调用 factorial(n - 1)。

计算 factorial(5) 的过程如下:

factorial(5) = 5 * factorial(4)

factorial(4) = 4 * factorial(3)

factorial(3) = 3 * factorial(2)

factorial(2) = 2 * factorial(1)

factorial(1) = 1 * factorial(0)

factorial(0) = 1(基准情况)

递归调用结束并逐步回溯,最终计算出结果 5! = 120。

匿名函数(Lambda函数)

在 Python 中,匿名函数(Anonymous Function)指的是没有名字的函数,通常使用 lambda 关键字来定义。匿名函数通常用于需要一个简单函数且只使用一次的场景。

名函数的语法非常简洁,使用 lambda 关键字定义,语法格式如下:

lambda 参数1, 参数2, ... : 表达式

lambda 是关键字,表示这是一个匿名函数。

参数1, 参数2, ... 是函数的参数,多个参数用逗号分隔。

表达式 是函数体,只能是一个表达式,计算结果就是这个函数的返回值。匿名函数的结果会自动返回,无需使用 return 关键字。

简单的匿名函数示例

一个简单的匿名函数,计算两个数的和:

add = lambda x, y: x + y

这个 lambda 表达式定义了一个匿名函数,并将其赋值给 add 变量。add 现在可以像普通函数一样使用:

result = add(3, 5)
print(result)  # 输出: 8

与普通函数的对比

匿名函数和普通函数(使用 def 关键字定义的函数)的主要区别在于匿名函数更适合定义简单的、一次性的函数。普通函数适用于更复杂的逻辑或者需要多次使用的情况下。

普通函数:

def add(x, y):return x + yresult = add(3, 5)
print(result)  # 输出: 8

匿名函数可写为:

add = lambda x, y: x + y
result = add(3, 5)
print(result)  # 输出: 8

在这个简单的例子中,匿名函数和普通函数的效果是一样的,但匿名函数更加简洁。

在使用像 map()、filter()、sorted()、reduce() 等高阶函数时,经常会用到匿名函数。关于高阶函数就不多说了。

这篇关于Python青少年简明教程:函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131671

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

利用Python打造一个Excel记账模板

《利用Python打造一个Excel记账模板》这篇文章主要为大家详细介绍了如何使用Python打造一个超实用的Excel记账模板,可以帮助大家高效管理财务,迈向财富自由之路,感兴趣的小伙伴快跟随小编一... 目录设置预算百分比超支标红预警记账模板功能介绍基础记账预算管理可视化分析摸鱼时间理财法碎片时间利用财

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

使用Python和Pyecharts创建交互式地图

《使用Python和Pyecharts创建交互式地图》在数据可视化领域,创建交互式地图是一种强大的方式,可以使受众能够以引人入胜且信息丰富的方式探索地理数据,下面我们看看如何使用Python和Pyec... 目录简介Pyecharts 简介创建上海地图代码说明运行结果总结简介在数据可视化领域,创建交互式地

利用python实现对excel文件进行加密

《利用python实现对excel文件进行加密》由于文件内容的私密性,需要对Excel文件进行加密,保护文件以免给第三方看到,本文将以Python语言为例,和大家讲讲如何对Excel文件进行加密,感兴... 目录前言方法一:使用pywin32库(仅限Windows)方法二:使用msoffcrypto-too