一 作用域

作用域介绍

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函数补充的更多相关文章

  1. Python之路----内置函数补充与匿名函数

    内置函数补充:reversed()保留原列表,返回一个反向的迭代器 l = [1,2,3,4,5] l.reverse() print(l) l = [1,2,3,4,5] l2 = reversed ...

  2. 《Python》 内置函数补充、匿名函数、递归初识

    一.内置函数补充: 1.数据结构相关(24): 列表和元祖(2):list.tuple list:将一个可迭代对象转化成列表(如果是字典,默认将key作为列表的元素). tuple:将一个可迭代对象转 ...

  3. python学习笔记:第14天 内置函数补充和递归

    一.匿名函数 匿名函数主要是为了解决一些简单需求而设计的一种函数,匿名函数的语法为: lambda 形参: 返回值 先来看一个例子: # 计算n的n次方 In[2]: lst = lambda n: ...

  4. Python开发基础-Day11内置函数补充、匿名函数、递归函数

    内置函数补充 python divmod()函数:把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b) 语法: divmod(a, b) #a.b为数字,a为除数,b ...

  5. python基础之内置函数补充、匿名函数、递归函数

    内置函数补充 python divmod()函数:把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b) 语法: 1 divmod(a, b) #a.b为数字,a为除数 ...

  6. python 之 面向对象(多态性、装饰器方法 内置函数补充)

    7.6 多态性 1 什么是多态性 多态指的是同一种事物多种形态,在程序中用继承可以表现出多态.多态性:可以在不用考虑对象具体类型的前提下而直接使用对象下的方法 2.为什要用多态 用基类创建一套统一的规 ...

  7. python 函数之day3

    一 函数的语法及特性 什么是函数? 定义:函数是一个功能通过一组语句的集合,由名字(函数名)将其封装起来的代码块,要想执行这个函数,只要调用其函数名即可. 特性: 减少重复代码 使程序变的可扩展 使程 ...

  8. Day4 内置函数补充、装饰器

    li = [11,22,33,44]def f1(arg): arg.append(55)#函数默认返回值None,函数参数传递的是引用li = f1(li) print(li)   内置函数补充: ...

  9. Python 函数基础、有序集合、文件操作(三)

    一.set 特点: set是一个无序且不重复的元素集合访问速度快:天生解决元素重复问题 方法: 初始化 >>> s1 = set()>>> print(type(s ...

随机推荐

  1. JQuery选择器大全 前端面试送命题:面试题篇 对IOC和DI的通俗理解 c#中关于协变性和逆变性(又叫抗变)帮助理解

    JQuery选择器大全   jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement")    选择id值等于myElement的元素 ...

  2. ZOJ 3827 Information Entropy (2014牡丹江区域赛)

    题目链接:ZOJ 3827 Information Entropy 依据题目的公式算吧,那个极限是0 AC代码: #include <stdio.h> #include <strin ...

  3. Atitit.获取swing ui 按钮控件的id 与名字 与JPDA 调试体系

    Atitit.获取swing ui 按钮控件的id 与名字 与JPDA 调试体系 1. Swing Inspector是一个Java Swing/AWT用户界面分析和调试工具,功能与firebug类似 ...

  4. ModelSim 使用笔记1

    ModelSim 使用笔记1   ModelSim提供了简单仿真方式,还有一种要建立project,目前这种方式暂时够我用了. 总结了以下,做了一个简单的<modelsim quick star ...

  5. iOS TableView索引字体大小设置

    -(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger ...

  6. ptmalloc、tcmalloc和jemalloc

    内存优化总结:ptmalloc.tcmalloc和jemalloc 转载 2017年09月05日 18:57:12 3674 转载于:http://www.cnhalo.net/2016/06/13/ ...

  7. 【Python + ATX基于uiaotumator2】之Android—APP自动化简易例子

    上代码: import uiautomator2 as u2 from time import sleep d = u2.connect_usb('608ad0fe') #打开小卖 # d(text= ...

  8. Spring MVC的@ResponseBody回来JSON串

    1 406错误 <mvc:annotation-driven />不用动,请求的时候URL的文件扩展名应为json @ResponseBody会根据扩展名,或者Header,或者Param ...

  9. cocos2dx-3.0(前言)

    说了好久,告诉自己要開始学cocos2dx(在心理里告诉了好久),然后养成良好习惯,记录自己学习cocos2dx的过程.一个是怕自己忘记.还有一个是更加让自己理解透彻(或许哪天我写的好了,组合一下出一 ...

  10. week 6: kernel regression

    华盛顿大学 machine learning regression 第六周笔记. 普通的回归方法是基于training set的整体性进行训练的,如果训练数据集 具有明显的分段性,那么普通的回归方法预 ...