[TimLinux] Python 函数(2)
1. 作用
- 最大化的代码重用:建设复制、粘贴
- 最小化的代码冗余:减少重复代码
- 流程分解:将做一件事情分解为相应的步骤,不同步骤封装在不同的函数中。
2. 定义
def 函数名(可选的参数列表):
函数体
函数名:命名需要符合Python标识符规范:开头不能为数字,只能包含字母、数字、下划线。
可选的参数列表:
- 一个参数都不需要,括号内什么都不填
- 位置参数:传递一个或多个参数,依次排列下去
- 关键字参数:通过使用 “名=值” 的方式来传递参数
- 变长的位置参数:*args,在一个变量名前面加上"*"号,可以将args列表中的每一项作为一个参数进行传递
- 变长的关键字参数:**kwargs,在一个变量名前面加上" ** ",可以将kwargs字典中的每一项作为一个参数进行传递
- 关键字参数必须在位置参数之后进行传递。
函数体:
- 空函数体,使用 pass 语句进行设置
- 其他内容按照正常逻辑编写Python代码,构成函数体。
2.1. 设计的概念
1. def : def 是语句中的一种,按照语句固有的格式来定义函数,函数并不存在,直到运行了def语句后,才存在,def语句可以嵌套在其他如:if, while, def等语句中。 2. def 创建了一个对象,并将对象赋值给一个变量名,执行def语句将生成一个函数对象,并最终赋值给了函数名,函数名是对某一函数的引用,函数名可以像其他变量名一样使用,
比如存入列表等。 3. lambda 创建了一个对象,但将其作为结果返回,lambda属于表达式,用于一条def语句不能工作的场景中。 4. return 将一个结果对象发送给调用者,将计算值返回给调用者。 5. yield 向调用者发回一个结果对象,但是记住它离开的地方,生成器函数的返回值是有yield语句返回的,每次返回后将挂起,并在下次调用时恢复。 6. global 声明了一个模块级的变量并被赋值。默认情况所有在变量中声明的变量只属于这个函数,函数的本地变量,生命周期是函数被调用时,global声明的变量来自模块最顶层。 7. nonlocal 声明了将要赋值的一个封闭的函数变量,变量冻结在函数作用域内,每次调用将继承上次变量最后的状态。 8. 函数是通过赋值(对象引用)传递的,参数是通过引用传递的,改变参数名不会改变实参的值,但是当传递的是一个可变对象(列表、字典等)则会导致共同使用的一片内存区域发生修改。 9. 参数、返回值以及变量并不是声明:Python没有类型约束,参数类型不受限制。
2.2. 多态
代码并不关心特定的数据类型,通过测试代码来替换编译器规定不同的数据类型,不需要:实现相同的功能,为不同的数据类型参数,编写多个函数。
2.3. 本地变量
所有本地变量都会在函数调用是出现,并在函数退出时消失。
3. 作用域
将一个变量名被赋值的地点(绑定给)关联为一个特定的命名空间。在代码中,给一个变量赋值的地方,决定了这个变量可见的范围。
- 模块存在一级作用域
- 类存在一级作用域
- 函数存在一级作用域
- 向前搜索,不向后搜索(比如JavaScript,它只存在函数级作用域,变量是可以认为会向后搜索的)
变量的作用域,只根变量被赋值的地方有关,与函数的调用等是无关的。
3.1. 作用域法则
嵌套的命名空间形成了作用域的规则。
- 函数定义了本地作用域
- 模块定义了全局作用域
两个作用域间的关系:
- 内嵌的模块是全局作用域:每个模块都是一个全局作用域。
- 全局作用域的作用范围仅限于单个文件:“全局”指的是一个文件顶层变量仅对这个文件内部代码而言是“全局”。
- 每次对函数的调用都创建了一个新的本地作用域。
- 赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量:默认函数内变量为本地作用域内,通过global、nonlocal间变量引用到全局变量、嵌套函数间变量。
- 所有其他的变量名都可以归纳为本地、全局、内置三种作用域。
3.2. 变量名解析机制(LEGB原则)
- L: Local,局部作用域
- E: Enclosing 直接外围作用域
- G: Global 全局作用域
- B: Builtin 内建作用域
变量四个查找步骤:1. 本地作用域,2. 函数内, 3. 全局, 4. 最后内置。任一步骤找到变量名立即停止,查找到最后一步都未找到报错。

3.3. 示例
x = 99
def f1(y):
z = x + y # x 来自global,但是不需要global关键字
return z
print(f1(2)) # 输出:101
x = 99
def f1(y):
print("f1: x + y = ", x+y)
def f2(z):
print("f2: x + z = ", x+z)
f2(2)
f1(1) # output:
# f1: x + y = 100
# f2: x + z = 101
# x 变量从全局移到函数内部,f1(1)在全局调用,f2(2)在f1(1)内部调用,工作正常。 # x = 99
def f1(y):
x = 88
print("f1: x + y = ", x+y)
def f2(z):
print("f2: x + z = ", x+z)
f2(2)
f1(1) # output:
# f1: x + y = 89
# f2: x + z = 90 # 这个例子也能够正常工作,是因为变量的查找顺序是匹配LEGB原则的。
# x = 99
def f1(y):
x = 88
print("f1: x + y = ", x+y)
def f2(z):
print("f2: x + z = ", x+z)
return f2
new_f2 = f1(1)
new_f2(2) # output:
# f1: x + y = 89
# f2: x + z = 90 # 而下面这段代码不能够工作,是因为x+=1是一条赋值语句,x属于E级作用域,在L级
# 作用域内赋值,跨作用域修改变量无法成功。
x = 99
def f1(y):
x = 88 # 这句成功了,是因为直接赋值,创建了一个L级作用域变量
print("f1: x + y = ", x+y)
def f2(z):
x += 1 # 代码等价 x = x + 1,第二个位置的x会在本地变量中查找,这是一个循环引用,导致提示以下错误。如果改为 w = x + 1,则不存在这样的问题。
print("f2: x + z = ", x+z)
return f2
new_f2 = f1(1)
new_f2(2) # output:
# Traceback (most recent call last):
# f1: x + y = 89
# File "D:/作用域.py", line 10, in <module>
# new_f2(2)
# File "D:/作用域.py", line 6, in f2
# x = x + 1
# UnboundLocalError: local variable 'x' referenced before assignment
3.4. global、nonlocal
- global:允许修改一个模块文件的顶层变量名(定义在def语句之外的变量名)。对变量修改,之后在访问变量,变量确实被修改了。
- nonlocal:允许修改一个def语句内最近一层变量名(比如多层嵌套def,查找nonlocal声明的变量,是查找最靠近nonlocal声明语句的位置)。对变量修改,之后在访问变量,变量也确实被修改了。
3.5. 闭包/工厂函数
一种记住临时对象的方法,当一个变量离开它的作用域,按照正常逻辑,变量应该被消亡,但是使用一种技术可以将这样的临时变量保存下,这就是闭包。
使用了闭包技术,能够技术这样的变量的函数,称为闭包函数,或者工厂函数。示例
def maker(n):
print("maker: n", n)
def tmp(x):
x *= n
print(x)
return tmp
f = maker(2)
f(2)
g = maker(3)
g(2) # output:
# maker: n 2
#
# maker: n 3
#
如果要对外部函数的变量进行修改,这时就需要使用nonlocal,使用将外部变量赋值新变量是无法每次调用记录上次值的功能的。
4. 函数参数
关键点:
- 参数的传递是通过自动将对象赋值给本地变量名来实现:
5. 高级话题
TBD
6. 迭代和解析
TBD.
[TimLinux] Python 函数(2)的更多相关文章
- [TimLinux] Python 函数
1. 函数(function)与方法(method)的区别 方法:在类结构体中通过def语句声明的代码块称为方法,比如类方法(classmethod),实例方法,静态方法(staticmethod)等 ...
- python 函数之day3
一 函数的语法及特性 什么是函数? 定义:函数是一个功能通过一组语句的集合,由名字(函数名)将其封装起来的代码块,要想执行这个函数,只要调用其函数名即可. 特性: 减少重复代码 使程序变的可扩展 使程 ...
- Python函数作用域的查找顺序
函数作用域的LEGB顺序 1.什么是LEGB? L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间 G:global 全局作用域 B:build-in 内置作用域 2.它们 ...
- Python函数讲解
Python函数
- Python函数信息
Python函数func的信息可以通过func.func_*和func.func_code来获取 一.先看看它们的应用吧: 1.获取原函数名称: 1 >>> def yes():pa ...
- Python函数参数默认值的陷阱和原理深究"
本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...
- Python开发【第四章】:Python函数剖析
一.Python函数剖析 1.函数的调用顺序 #!/usr/bin/env python # -*- coding:utf-8 -*- #-Author-Lian #函数错误的调用方式 def fun ...
- Python函数解析
对于Python的函数,我们需要记住的是: 1. 函数的默认返回值是None. 2. python是一个自上而下逐行解释并执行的语言.因此,函数的定义必须在函数被调用之前.同名的函数,后定义的会覆盖前 ...
- Python入门笔记(18):Python函数(1):基础部分
一.什么是函数.方法.过程 推荐阅读:http://www.cnblogs.com/snandy/archive/2011/08/29/2153871.html 一般程序设计语言包含两种基本的抽象:过 ...
随机推荐
- Vue基础系列(四)——Vue中的指令(上)
写在前面的话: 文章是个人学习过程中的总结,为方便以后回头在学习. 文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. VUE基础系列目录 < ...
- Golang stackError 补充go错误定位能力
用过go的都知道,go的error实现很简单,errors.New实现的error类并不存储堆栈数据,这导致一个问题,就是多次error return后,或panic后recover了,找不到触发异常 ...
- 【R语言学习笔记】 Day1 CART 逻辑回归、分类树以及随机森林的应用及对比
1. 目的:根据人口普查数据来预测收入(预测每个个体年收入是否超过$50,000) 2. 数据来源:1994年美国人口普查数据,数据中共含31978个观测值,每个观测值代表一个个体 3. 变量介绍: ...
- MathType转Word公式(OMML)
背景 由于之前个人喜欢在Word里做笔记,而有很多笔记里存在着大量的公式.在早期,由于对Word自身的公式的不理解,所以便使用了MathType这个工具来编写公式.但是现在本人已经转战到LatTeX了 ...
- Laravel框架安装RabbitMQ消息中间件步骤
Laravel5.6 整合 RabbitMQ 消息队列 简介: Laravel 队列为不同的后台队列服务提供了统一的 API,例如 Beanstalk,Amazon SQS,Redis,甚至其他基于关 ...
- Freemarker + xml 实现Java导出word
前言 最近做了一个调查问卷导出的功能,需求是将维护的题目,答案,导出成word,参考了几种方案之后,选择功能强大的freemarker+固定格式之后的wordxml实现导出功能.导出word的代码是可 ...
- 记一次LDAP主从同步配置
LDAP主从同步 OpenLDAP在2.3版本之前的同步复制带有一系列缺点如只支持一主多从模式等,在此缺点就不多说,下文着重介绍一下OpenLDAP V2.4以后的同步负复制功能 同步功能 2.4版最 ...
- LaravelS - 基于Swoole加速Laravel/Lumen
LaravelS LaravelS是一个胶水项目,用于快速集成Swoole到Laravel或Lumen,然后赋予它们更好的性能.更多可能性.Github 特性 内置Http/WebSocket服务器 ...
- 【论文阅读】The Contextual Loss for Image Transformationwith Non-Aligned Data(ECCV2018 oral)
目录: 相关链接 方法亮点 相关工作 方法细节 实验结果 总结与收获 相关链接 论文:https://arxiv.org/abs/1803.02077 代码:https://github.com/ro ...
- Linux下为知笔记和蚂蚁笔记测评,推荐蚂蚁笔记!(非广告)
本人由于学习Linux,需要一款可以在Linux平台下可以运行的一款软件,了解到为知笔记之笔记(下文以W代替)和蚂蚁笔记(下文以M代替)比较出名,由于某云和某象笔记在linux平台下没有对应的软件,所 ...