文章目录

  • 函数和过程
  • 函数变量的作用域
    • 局部变量
    • 全局变量
    • global关键字
  • 内嵌函数(内部函数)
  • 闭包(closure)
  • lambda表达式
  • 两个常用BIF:filter()和map()

函数和过程

在许多编程语言中,函数和过程其实是分开的。一般认为函数(function)是有返回值的,而过程(procedure)是简单、特殊并且没有返回值的。Python严格来说,只有函数,没有过程。举个例子:

调用print(hello())之后打印了两行文字,第一行我们当然知道是hello()函数执行的,第二行的None是怎么回事呢?其实,当不写return语句的时候,默认Python会认为函数是return None的。所以说Python所有的函数都有返回值


函数变量的作用域

也许大家已经听说了局部变量和全局变量,变量的作用域也就是平常所说的变量可见性,一般的编程语言都有局部变量(Local Variable)全局变量(Global Variable) 之分。

# 计算折扣价
def discounts(price, rate):final_price = price * ratereturn final_priceold_price = float(input("请输入原价:"))
rate = float(input("请输入折扣率:"))
new_price = discounts(old_price, rate)
print("打折后的价格是:", new_price)

其执行结果如下:


局部变量

这是一个简单的计算折扣价的代码段,来分析一下代码:在函数discounts()中,两个参数是price和rate,还有一个是final_price它们都是discounts()函数中的局部变量。为什么称为局部变量呢,不妨修改一下代码:

# 计算折扣价
def discounts(price, rate):final_price = price * ratereturn final_priceold_price = float(input("请输入原价:"))
rate = float(input("请输入折扣率:"))
new_price = discounts(old_price, rate)
print("打折后的价格是:", new_price)# 添加一行试图打印局部变量final_price的值
print("打印局部变量final_price的值:", final_price)

可以看到程序像刚才一样输出之后便报错了,错误原因是:final_price没有被定义过,也就是说,Python找不到final_price这个变量。这是因为final_price只是一个局部变量,它的作用只在它的地盘上——discounts()函数的定义范围内——有效,出了这个范围,就不属于它的地盘了,它将什么都不是。

总结一下:在函数里边定义的参数以及变量,都称为局部变量,出了这个函数,这些变量都是无效的。 事实上的原理是,Python在运行函数的时候,利用栈(Stack)进行存储,当执行完该函数后,函数中的所有数据都会被自动删除,所以在函数外边是无法访问到函数内部的局部变量的。


全局变量

与局部变量相对的是全局变量,程序中的old_price、new_price、rate都是在函数外边定义的,它们都是全局变量,全局变量拥有更大的作用域,例如在函数中可以访问到它们:

# 计算折扣价
def discounts(price, rate):final_price = price * rate# 添加一行试图打印全局变量old_price的值print("打印全局变量old_price的值:", old_price)return final_priceold_price = float(input("请输入原价:"))
rate = float(input("请输入折扣率:"))
new_price = discounts(old_price, rate)
print("打折后的价格是:", new_price)

其执行结果为:

可以看到全部变量的访问范围更广,不过使用全局变量的时候要千万小心,在Python中,你可以在函数中肆无忌惮的访问一个全局变量,但是如果你试图去修改它,就会出现下面这样的结果

# 计算折扣价
def discounts(price, rate):final_price = price * rateold_price = 50  # 这里试图修改全部变量print("在局部变量中修改后的old_price的值是:", old_price)return final_priceold_price = float(input("请输入原价:"))
rate = float(input("请输入折扣率:"))
new_price = discounts(old_price, rate)
print("全局变量old_price现在的值是:", old_price)
print("打折后的价格是:", new_price)

其执行结果为:

出现这个结果的原因是:如果在函数内部试图修改全局变量,那么Python会创建一个新的局部变量替代(名字跟全局变量相同),但真正的全部变量是没有改变的,所以实现会和大家预期的不同。

总结一下:全局变量在整个代码段中都是可以访问到的,但是不要试图在函数内部去修改全局变量的值,因为那样Python会自动在函数内部新建一个名字相同的局部变量代替。


global关键字

上面提到,全局变量的作用域是整个模块,也就是代码段内所有的函数内部都可以访问到全局变量。但需要注意的是,在函数内部仅仅访问全局变量可以,不要试图去修改它。因为那样的话,Python会使用 屏蔽(Shadowing) 的方式“保护”全局变量:一旦函数内部试图修改全局变量,Python就会在函数内部自动创建一个名字一样的局部变量,这样修改的结果只会修改到局部变量,而不会影响全局变量。举个小例子:

如果你认为有必要在函数中去修改这个全局变量,那么你不妨可以使用global关键字来达到目的


内嵌函数(内部函数)

Python的函数定义是可以嵌套的,也就是允许在函数内部创建另一个函数,这种函数叫作内嵌函数或者内部函数。下面看一个简单的内嵌函数的例子:

关于内部函数的使用,有一个比较值得注意的地方,就是内部函数整个作用域都在外部函数之内,就像上述例子中的fun2()整个函数的作用域都在fun1()里边。除了在fun1()这个函数体中可以随意调用fun2()这个内部函数外,出了fun1(),就没有任何可以对fun2()进行的调用。
如果在fun1()外调用内部函数fun2(),就会报错


闭包(closure)

闭包(closure)是函数式编程的一个重要的语法结构,函数式编程是一种编程范式,不同的编程语言实现闭包的方式不同,Python中的闭包从表现形式上定义为如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。举个例子:

也可以这样写:

通过上面的例子来理解闭包的概念:如果在一个内部函数里(funY就是这个内部函数)对外部作用域(但不是在全局作用域)的变量进行引用(x就是被引用的变量,x在外部作用域funX函数里面,但不在全局作用域里),则这个内部函数(funY)就是一个闭包

使用闭包需要注意的是,因为闭包的概念就是由内部函数而来的,所以也不能在外部函数以外的地方对内部函数进行调用

在闭包中,外部函数的局部变量对应内部函数的局部变量,事实上相当于之前讲的全局变量跟局部变量的对应关系,在内部函数中,只能对外部函数的局部变量进行访问,但不能进行修改

再看一个例子:

这个报错信息跟之前讲解全局变量的时候基本一样,Python认为在内部函数(funY)的x是局部变量的时候,外部函数(funX)的x就被屏蔽了起来,所以执行 x *= x 的时候,在右边根本就找不到局部变量x的值,因此报错。

而在Python3中,对于这个问题,也有解决办法——nonlocal关键字
如果希望在内部函数里可以修改外部函数里的局部变量的值,那么就可以使用nonlocal关键字,使用方式和global关键字一样:


lambda表达式

Python允许使用lambda关键字来创建匿名函数
Python中的lambda表达式语法非常精简,其基本语法是:
参 数 1 , 参 数 2 , . . . : 返 回 值 参数1,参数2,... : 返回值 参数1,参数2,...:返回值
在冒号(:)左边放原函数的参数,可以有多个参数,用逗号(,)隔开即可;冒号右边是返回值

给一个简单的例子:

其写为lambda表达式来定义这个函数,就会变为这样:

我们发现lambda语句实际上是返回一个函数对象,如果要对它进行使用,只需要进行简单的赋值操作即可:

当然,如果有多个参数直接用逗号隔开即可:

lambda表达式的作用:
1、 Python写一些执行脚本时,使用lambda就可以省下定义函数过程,就不需要专门定义一个函数然后再写调用,使用lambda就可以使得代码更加精简。
2、 对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候给函数起名是个比较头疼的问题,使用lambda就不需要考虑命名的问题了。
3、 简化代码的可读性,由于阅读普通函数经常要跳到开头def定义的位置,使用lambda函数可以省去这样的步骤。


两个常用BIF:filter()和map()

接下来介绍两个比较实用的BIF:filter()和map()。

一、filter()

这一个内建函数是一个过滤器。我们每天会接触大量的数据,通过过滤器,就可以保留你所关注的信息,把其他不感兴趣的东西直接丢掉。那么Python中的这个filter()是怎么实现这个功能呢?先来看一下Python给出的函数部分注释:

这里只截取了关于函数用法的部分,大概意思是:filter有两个参数,第一个参数可以是一个函数也可以是None,如果第一个参数是一个函数的话,则将第二个可迭代数据里的每一个元素作为函数的参数进行计算,把返回True的值筛选出来;如果第一个参数为None,则直接将第二个参数中为True的值筛选出来。

举几个简单例子:

1、 第一个参数为None时

2、利用filter(),写一个筛选奇数的过滤器

在学习了lambda表达式后,可以将上述过程转换为一行:

二、map()

map()这个内置函数也有两个参数,仍然是一个函数一个可迭代序列,将序列的每一个元素作为函数的参数进行运算加工,直到可迭代序列每个元素都加工完毕,返回所有加工后的元素构成的新序列

其用法和filter()类似,举个简单的例子:

Python基础——函数(二)相关推荐

  1. Python基础(二)--数据类型,运算符与流程控制

    目录 Python基础(二)--数据类型,运算符与流程控制 1 数据类型 1.1 Python中的数据类型 1.2 整数类型(int) 1.3 布尔类型 1.4 浮点类型 1.5 复数类型 1.6 类 ...

  2. Python基础(二)完结

    今天分享又来了呀.ღ( ´・ᴗ・` ) 一起学习进步ღゝ◡╹)ノ♡ 关注公众号,回复"资料全集",不定期最新大数据业内资讯. ❤:在这里跟我一起学习技术.职场.人生.原理.健身.摄 ...

  3. python 基础复习二

    这里写自定义目录标题 python 基础复习二 1.数据类型 2.数据的应用 3.数据的转换 总结 python 基础复习二 1.数据类型 最常用的数据类型有三种--字符串(str).整数(int)和 ...

  4. 廖雪峰Python基础练习(二)

    #廖雪峰Python基础练习(二)# 请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串: 答: # -*- coding: utf-8 -*-n1 = 255 n2 = 10 ...

  5. Python基础-函数,高阶函数

    Python基础-函数 1.函数的定义和函数的执行流程: """ 函数学习 """print('程序开始') a = 10 # 在内存中申请 ...

  6. 数据挖掘之Python基础(二)函数与文件读写

    前言 前一篇文章我们讲到了Python的基本的数据结构,如果对于Python不是很熟悉,建议先看前一篇文章,或者关注公众号QStack,里面有全部文章. if条件语句 基本所有语言的if条件语句都差不 ...

  7. 第三章:Python基础の函数和文件操作实战

    本課主題 Set 集合和操作实战 函数介紹和操作实战 参数的深入介绍和操作实战 format 函数操作实战 lambda 表达式介绍 文件操作函数介紹和操作实战 本周作业 Set 集合和操作实战 Se ...

  8. python基础函数大全pdf,python函数大全及使用

    Python的函数都有哪些? Python 函数函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数, ...

  9. python请输入姓名性别以及年龄jack男20_【详细】Python基础(二)

    文章目录 前言 7. 公共操作 7.1 运算符 7.2 公共方法 7.3 容器类型转换 8. 推导式 8.1 列表推导式 8.2 字典推导式 8.3 集合推导式 8.4 推导式总结 9. Python ...

最新文章

  1. Linux的Unicon资料
  2. 学习人必看!空军老兵自学编程,仅隔一年成为国土安全部的数据库分析师
  3. excel公式 某一个单元格等于另一个单元格的值_EXCEL函数学习5——COUNTIF函数
  4. sublime text 2中Emmet8个常用的技巧
  5. spark减少内存消耗_将内存消耗减少20倍
  6. python画折线图代码实现_python如何绘制分布折线图 python绘制分布折线图代码示例...
  7. codis配置_Codis的安装配置
  8. mave构建docker镜像Dokerfile,上传华为云镜像服务器CCE
  9. 设计模式-第一篇之单例模式
  10. anaconda简单解决PackagesNotFoundError: The following packages are not available from current channels:
  11. UDS常用诊断服务介绍
  12. stm32电容触摸按键的实现
  13. 手动实现获取微信openid
  14. Last chance to join 500+ others in Australia
  15. 视频水印怎么去掉?有什么好的去水印工具吗?
  16. tf.layers.flatten()使用
  17. wxpy 微信聊天机器人的实现
  18. 小马智行联合创始人兼CTO楼天城:无人驾驶:一场科技主导的“登月之旅”
  19. python 视频教程大全下载地址
  20. 应对口译口试之三大策略

热门文章

  1. 每日一课 | 使用JavaScript强制下载(文末免费领好课)
  2. shineblink Core1602LCD显示
  3. Elasticsearch的CRUD最简单的操作
  4. 什么是灵活的软件授权模式,如何选择软件加密狗?
  5. 2021 年 7 个较佳的免费电子商务平台(比较)
  6. 模拟芯片测试之OS测试
  7. python枚举类的意义_python 枚举类型什么意思
  8. MarkDownPad 2 表格样式修改
  9. 干货分享 | 这个软件一秒钟就可以知道你电脑有什么
  10. 【多图预警,不懂来敲我】图说HashMap原理和流程