python函数补充
一 作用域
作用域介绍
python中的作用域分4种情况:
L:local,局部作用域,即函数中定义的变量;
E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局 部作用域,但不是全局的;
G:globa,全局变量,就是模块级别定义的变量;
B:built-in,系统固定模块里面的变量,比如int, bytearray等。 搜索变量的优 先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置 作用域,也就是LEGB。
x = int(2.9) # int built-ing_count = 0 # globaldef outer(): o_count = 1 # enclosing def inner(): i_count = 2 # local print(o_count) # print(i_count) 找不到 inner() outer()# print(o_count) #找不到
当然,local和enclosing是相对的,enclosing变量相对上层来说也是local。
作用域产生
在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)是不会引入新的作用域的,如下代码:
if 2>1: x = 1print(x) # 1
这个是没有问题的,if并没有引入一个新的作用域,x仍处在当前作用域中,后
面代码可以使用。
def test(): x = 2print(x) # NameError: name 'x2' is not defined
def、class、lambda是可以引入新作用域的。
变量的修改
x=6def f2(): print(x) x=5f2() # 错误的原因在于print(x)时,解释器会在局部作用域找,会找到x=5(函数已经加载到内存),但x使用在声明前了,所以报错:# local variable 'x' referenced before assignment.如何证明找到了x=5呢?简单:注释掉x=5,x=6# 报错为:name 'x' is not defined#同理x=6def f2(): x+=1 #local variable 'x' referenced before assignment.f2()
global关键字
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了,当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下,代码如下:
count = 10def outer(): global count print(count) count = 100 print(count)outer()#10#100
nonlocal关键字
global关键字声明的变量必须在全局作用域上,不能嵌套作用域上,当要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量怎么办呢,这时就需要nonlocal关键字了
def outer(): count = 10 def inner(): nonlocal count count = 20 print(count) inner() print(count)outer()#20#20
小结
(1)变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局 >python内置作用域;
(2)只有模块、类、及函数才能引入新作用域;
(3)对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用, 就会使用外部作用域的变量;
(4)内部作用域要修改外部作用域变量的值时,全局变量要使用global关键 字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关 键字,有了这个 关键字,就能完美的实现闭包了。
二 递归函数
定义:在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
实例1(阶乘)
def factorial(n): result=n for i in range(1,n): result*=i return resultprint(factorial(4))
#**********递归*********def factorial_new(n): if n==1: return 1 return n*factorial_new(n-1)print(factorial_new(3))
实例2(斐波那契数列)
def fibo(n): before=0 after=1 for i in range(n-1): ret=before+after before=after after=ret return retprint(fibo(3))
#**************递归*********************def fibo_new(n):#n可以为零,数列有[0] if n <= 1: return n return(fibo_new(n-1) + fibo_new(n-2))print(fibo_new(3))print(fibo_new(30000))#maximum recursion depth exceeded in comparison
递归函数的优点: 是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈 (stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈 帧,每当函数返 回,栈就会减一层栈帧。由于栈的大小不是无限的,所 以,递归调用的次数过多,会导致栈溢出。)
三 内置函数(Py3.6)
重要的内置函数:
filter(function, sequence)
str = ['a', 'b','c', 'd']def fun1(s): if s != 'a': return sret = filter(fun1, str)print(list(ret))# ret是一个迭代器对象
对sequence中的item依次执行function(item),将执行结果为True的item做成一个filter object的迭代器返回。可以看作是过滤函数。
map(function, sequence)
str = [1, 2,'a', 'b']def fun2(s): return s + "alvin"ret = map(fun2, str)print(ret) # map object的迭代器print(list(ret))# ['aalvin', 'balvin', 'calvin', 'dalvin']
对sequence中的item依次执行function(item),将执行结果组成一个map object迭代器返回.
map也支持多个sequence,这就要求function也支持相应数量的参数输入:
ef add(x,y): return x+yprint (list(map(add, range(10), range(10))))##[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
reduce(function, sequence, starting_value)
from functools import reducedef add1(x,y): return x + yprint (reduce(add1, range(1, 101)))## 4950 (注:1+2+...+99)print (reduce(add1, range(1, 101), 20))## 4970 (注:1+2+...+99+20)
对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用.
lambda
普通函数与匿名函数的对比:
#普通函数def add(a,b): return a + bprint add(2,3)
#匿名函数add = lambda a,b : a + bprint add(2,3)#========输出===========55
匿名函数的命名规则,用lamdba 关键字标识,冒号(:)左侧表示函数接收的参数(a,b) ,冒号(:)右侧表示函数的返回值(a+b)。
因为lamdba在创建时不需要命名,所以,叫匿名函数
四 函数式编程
学会了上面几个重要的函数后,我们就可以来聊一聊函数式编程到底是个什么鬼
概念(函数式编程)
函数式编程是一种编程范式,我们常见的编程范式有命令式编程(Imperative programming),函数式编程,常见的面向对象编程是也是一种命令式编程。
命令式编程是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取,存储指令),表达式(内存引用和算术运算)和控制语句(跳转指令),一句话,命令式程序就是一个冯诺依曼机的指令序列。
而函数式编程是面向数学的抽象,将计算描述为一种表达式求值,一句话,函数式程序就是一个表达式。函数式编程关心数据的映射,命令式编程关心解决问题的步骤,这也是为什么“函数式编程”叫做“函数式编程”。
实例
#计算数组中正整数的平均值
number =[2, -5, 9, -7, 2, 5, 4, -1, 0, -3, 8]count = 0sum = 0for i in range(len(number)): if number[i]>0: count += 1 sum += number[i]print sum,countif count>0: average = sum/countprint average#========输出===========30 65
首先循环列表中的值,累计次数,并对大于0的数进行累加,最后求取平均值。 这就是命令式编程——你要做什么事情,你得把达到目的的步骤详细的描述出来,然后交给机器去运行。
这也正是命令式编程的理论模型——图灵机的特点。一条写满数据的纸带,一条根据纸带内容运动的机器,机器每动一步都需要纸带上写着如何达到。
那么,不用这种方式如何做到呢?
number =[2, -5, 9, -7, 2, 5, 4, -1, 0, -3, 8]positive = filter(lambda x: x>0, number)average = reduce(lambda x,y: x+y, positive)/len(positive)print average#========输出===========5
这段代码最终达到的目的同样是求取正数平均值,但是它得到结果的方式和 之前有着本质的差别:通过描述一个列表->正数平均值 的映射,而不是描述“从列表得到正数平均值应该怎样做”来达到目的。
函数式编程有什么好处呢?
1)代码简洁,易懂。
2)无副作用
由于命令式编程语言也可以通过类似函数指针的方式来实现高阶函数,函数式的最主要的好处主要是不可变性带来的。没有可变的状态,函数就是引用透明(Referential transparency)的和没有副作用(No Side Effect)。
python函数补充的更多相关文章
- Python之路----内置函数补充与匿名函数
内置函数补充:reversed()保留原列表,返回一个反向的迭代器 l = [1,2,3,4,5] l.reverse() print(l) l = [1,2,3,4,5] l2 = reversed ...
- 《Python》 内置函数补充、匿名函数、递归初识
一.内置函数补充: 1.数据结构相关(24): 列表和元祖(2):list.tuple list:将一个可迭代对象转化成列表(如果是字典,默认将key作为列表的元素). tuple:将一个可迭代对象转 ...
- python学习笔记:第14天 内置函数补充和递归
一.匿名函数 匿名函数主要是为了解决一些简单需求而设计的一种函数,匿名函数的语法为: lambda 形参: 返回值 先来看一个例子: # 计算n的n次方 In[2]: lst = lambda n: ...
- Python开发基础-Day11内置函数补充、匿名函数、递归函数
内置函数补充 python divmod()函数:把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b) 语法: divmod(a, b) #a.b为数字,a为除数,b ...
- python基础之内置函数补充、匿名函数、递归函数
内置函数补充 python divmod()函数:把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b) 语法: 1 divmod(a, b) #a.b为数字,a为除数 ...
- python 之 面向对象(多态性、装饰器方法 内置函数补充)
7.6 多态性 1 什么是多态性 多态指的是同一种事物多种形态,在程序中用继承可以表现出多态.多态性:可以在不用考虑对象具体类型的前提下而直接使用对象下的方法 2.为什要用多态 用基类创建一套统一的规 ...
- python 函数之day3
一 函数的语法及特性 什么是函数? 定义:函数是一个功能通过一组语句的集合,由名字(函数名)将其封装起来的代码块,要想执行这个函数,只要调用其函数名即可. 特性: 减少重复代码 使程序变的可扩展 使程 ...
- Day4 内置函数补充、装饰器
li = [11,22,33,44]def f1(arg): arg.append(55)#函数默认返回值None,函数参数传递的是引用li = f1(li) print(li) 内置函数补充: ...
- Python 函数基础、有序集合、文件操作(三)
一.set 特点: set是一个无序且不重复的元素集合访问速度快:天生解决元素重复问题 方法: 初始化 >>> s1 = set()>>> print(type(s ...
随机推荐
- Idea Cannot import to svn: Cannot run program "svn"
svn 出此问题:意味着不可检出代码. 按此修改,重启IDEA即可检出svn代码.
- vs mvc 视图中找不到 viewdata viewbag的解决方案
1.查看views下的web.config文件是否存在 2.检查config中system.web.mvc ,version中版本号与自己的vs内置mvc版本一致 迁移项目可能有此问题
- Predix中模型设计
GE的Predix使用了图形数据库作为Asset存储,用以解决传统RDBMS系统中扩展性差,不支持行的动态定义问题. 对于实体,或者Asset来说,由如下几个方面表述: ID: Ties everyt ...
- php对象序列化总出错false
php unserialize 返回false的解决方法 php 提供serialize(序列化) 与unserialize(反序列化)方法. 使用serialize序列化后,再使用unseriali ...
- Effective C++ 条款47
本节条款的题目:请使用trait classes来表示类型信息 本节条款主要讲述的技术是怎样在编译期间实现对迭代器类型的推断,依据推断的类型进行最优处理. 我们先来看一下迭代器的种类: 1.input ...
- mock异常
在类开始的时候: @Rule public ExpectedException expectedEx = ExpectedException.none(); 在方法中执行下面代码: expectedE ...
- Could not calculate build plan
问题:根据你提供的镜像地址,下载相应的jar包失败 原因: 1.你提供的镜像地址不稳定,把settings.xml文件中的mirror改成稳定的镜像地址 2.网络不稳定,重新下载,或者切换网络.
- StoryBoard不使用AutoLayout情况下 按比例快速兼容适配iPhone6/6 Plus教程【转载】
StoryBoard不使用AutoLayout情况下 按比例快速兼容适配iPhone6/6 Plus教程[转] 声明:本文章是为了后期快速兼容6和6Plus的按比例放大方法,对于部分读者来说可能觉得该 ...
- Who's in the Middle - poj 2388 (快速排序寻找中位数)
题意; 寻找中位数 利用快速排序来寻找中位数. #include <iostream> using namespace std; int N; ]; int Median(int left ...
- Java基础10 接口的继承与抽象类(转载)
接口继承 接口继承(inheritance)与类继承很类似,就是以被继承的interface为基础,增添新增的接口方法原型.比如,我们以Cup作为原interface: interface Cup{ ...