【函数】02、函数进阶

一、函数的返回值

In [4]: def add(x, y):
   ...:     return x+y
   ...: 

In [5]: add(1, 2)
Out[5]: 3

In [8]: def add(x, y):
   ...:     return x+y
   ...:     print(x+y)
   ...:     

In [9]: add(1, 2)
Out[9]: 3

In [16]: def add(x, y):
    ...:     return "abc", x+y
    ...:     return x+y
    ...:     

In [17]: add(1, 2)
Out[17]: (‘abc‘, 3)

  
In [18]: def add(x, y):
    ...:     return
    ...: 
    ...:     

In [19]: add(1, 2)

In [20]: a = add(1, 2)

In [21]: a

In [22]: type(a)
Out[22]: NoneType

In [25]: def add(x, y):
    ...:     return None
    ...: 

In [26]: add(1, 2)

In [27]: type(add(1, 2))
Out[27]: NoneType

关键字:return

return只能出现在函数中,可以返回任何对象,可以作为元祖变相的返回多个值

所有函数都有返回值,如果没定义return则默认返回值None

return语句除了返回值之外还会结束函数

1个函数可以有多个return语句,但只会执行一个

二、作用域

1、函数嵌套

函数可以嵌套定义

In [28]: def outter():
    ...:     def inner():
    ...:         print(‘inner‘)
    ...:     print(‘outter‘)
    ...:     inner()
    ...:     

In [29]: outter()
outter
inner

2、作用域

作用域是一个变量的可见范围

函数内部是一个局部作用域,外面叫全局作用域

不同作用域变量不可见,但是上级作用域的变量对下级只读可见

In [32]: x = 1

In [33]: def inc():
    ...:     x += 1   # x此时是局部变量,不能直接使用全局作用域的变量
    ...:     

In [34]: inc()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-34-ae671e6b904f> in <module>()
----> 1 inc()

<ipython-input-33-661b9217054c> in inc()
      1 def inc():
----> 2     x += 1
      3 

UnboundLocalError: local variable ‘x‘ referenced before assignment

In [40]: x = 1

In [41]: def fn():
    ...:     print(x)   
    ...:     

In [42]: fn()    # 为什么这里能打印出来,不抛出错误呢
1

变量的作用域为定义此变量的作用域:

In [43]: def fn():
    ...:     name = "xxj"
    ...:     print(name)
    ...:     

In [44]: fn()
xxj

In [45]: name
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-45-18697449d7c4> in <module>()
----> 1 name

NameError: name ‘name‘ is not defined

上级作用域对下级作用域是只读可见的

In [46]: def fn():
    ...:     xx = 1
    ...:     print(xx)
    ...:     def inner():
    ...:         print(xx)
    ...:     inner()
    ...:     

In [47]: fn()
1
1

In [48]: def fn():
    ...:     xx = 1
    ...:     print(xx)
    ...:     def inner():
    ...:         xx = 2
    ...:         print(xx)
    ...:     inner()
    ...:     print(xx)
    ...:     

In [49]: fn()
1
2
1

函数中可以显式定义提升变量作用域,global的提升只在本作用域及上级作用域有效:

In [53]: xx = 1

In [54]: def fn():
    ...:     global xx    # global关键字能显式的提升1个变量的作用域
    ...:     xx += 1
    ...:     

In [55]: fn()

In [56]: xx
Out[56]: 2

In [57]: fn()

In [58]: xx
Out[58]: 3

In [68]: xxj
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-68-bc382da45e82> in <module>()
----> 1 xxj

NameError: name ‘xxj‘ is not defined

In [69]: def fn():
    ...:     global xxj     # 如果此变量没有定义,则此提升变量作用域没有意义 
    ...:     
    ...:     

In [70]: fn()

In [71]: xxj
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-71-bc382da45e82> in <module>()
----> 1 xxj

NameError: name ‘xxj‘ is not defined

除非你清楚的知道global会带来什么,并且明确的知道没有global不行的话,否则不要用global;就是不建议使用global关键字

3、命名空间与LEGB

 1)命名空间 

理解Python的LEGB原则是理解Python命名空间的关键,而理解Python的命名空间又是理解Python中许多语法规定的关键。所以,Python的LEGB原则就成为Python中一个非常核心的内容

白话一点讲:命名空间是对变量名的分组划分。
       不同组的相同名称的变量视为两个独立的变量,因此隶属于不同分组(即命名空间)的变量名可以重复。
命名空间可以存在多个,使用命名空间,表示在该命名空间中查找当前名称。

命名空间表示变量的可见范围,一个变量名可以定义在多个不同的命名空间,相互之间并不冲突,但同一个命名空间中不能有两个相同的变量名。

比如:两个叫“张三”的学生可以同时存在于班级A和班级B中,如果两个张三都是一个班级,那么带来的麻烦复杂很多了,在Python中你不能这么干。

在Python中用字典来表示一个命名空间,命名空间中保存了变量(名字)和对象的映射关系,在Python中命名空间出现在哪些地方呢?有函数范围内的命名空间(local),有模块范围内的命名空间(global),有python内建的命名空间(built-in),还有类对象的所有属性组成的命名空间

Python一切皆对象,所以在Python中变量名是字符串对象

例如:


1

In [25]: a=10

表示建立字符串对象aNumber对象10之间的对应关系。由于这是一种映射关系,所以,可以使用键-值的形式来表示,即{name : object}
前面已经说过,命名空间是对变量名的分组划分,所以,Python的命名空间就是对许多键-值对的分组划分,即,键值对的集合,因此:

Python的命名空间是一个字典,字典内保存了变量名称与对象之间的映射关系

 2)命名空间的生命周期

所有的命名空间都是有生命周期的,对于python内建的命名空间,python解析器启动时创建,一直保留直至直python解析器退出时才消亡。而对于函数的local命名空间是在函数每次被调用的时候创建,调用完成函数返回时消亡,而对于模块的global命名空间是在该模块被import的时候创建,解析器退出时消亡。

 3)作用域

  一个作用域是指一段程序的正文区域,可以是一个函数或一段代码。

一个变量的作用域是指该变量的有效范围。Python的作用域是静态作用域,因为它是由代码中得位置决定的,而命名空间就是作用域的动态表现。

函数定义了本地作用域,而模块定义了全局作用域:

每个模块都是一个全局作用域,因此,全局作用域的范围仅限于单个程序文件

每次对函数的调用都会创建一个新的本地作用域,赋值的变量除非声明为全局变量,否则均为本地变量

所有的变量名都可以归纳为本地,全局或内置的(由__builtin__模块提供)

 4)LEGB原则

LEGB含义解释:
       L-Local(function);函数内的名字空间
       E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)
       G-Global(module);函数定义所在模块(文件)的名字空间
       B-Builtin(Python);Python内置模块的名字空间,builtin作用域,对应builtin命名空间,python内部定义的最顶层的作用域,在这个作用域里面定义了各种内建函数:open、range、xrange、list等等

前面讲到,Python的命名空间是一个字典,字典内保存了变量名与对象之间的映射关系,

因此,查找变量名就是在命名空间字典中查找键-值对
Python有多个命名空间,因此,需要有规则来规定,按照怎样的顺序来查找命名空间,LEGB就是用来规定命名空间查找顺序的规则。

LEGB规定了查找一个名称的顺序为:local-->enclosing function locals-->global-->builtin

三、闭包

当一个函数结束了,函数的内部部分变量引用还存在,这就叫闭包

python的闭包可以使用可变容器实现,这也是python2唯一的方式

In [91]: def counter():
    ...:     c = [0]
    ...:     def inc():
    ...:         c[0] += 1
    ...:         return c
    ...:     return inc
    ...: 

In [92]: type(counter)
Out[92]: function

In [93]: type(counter())
Out[93]: function

In [94]: type(counter()())
Out[94]: list

In [95]: f = counter()

In [96]: f()
Out[96]: [1]

In [97]: f()
Out[97]: [2]

In [98]: f()
Out[98]: [3]

nonlocal关键字:

nonlocal用于标记一个变量由它的上级作用域定义,通过nonlocal标记的变量可读可写

如果nonlocal标记的变量不存在则会抛出语法错误

In [102]: def counter():
     ...:     x = 0
     ...:     def inc():
     ...:         nonlocal x
     ...:         x += 1
     ...:         return x
     ...:     return inc
     ...: 

In [103]: f = counter()

In [104]: f()
Out[104]: 1

In [105]: f()
Out[105]: 2

In [106]: f()
Out[106]: 3
时间: 2024-08-25 13:05:20

【函数】02、函数进阶的相关文章

JavaScript进阶系列02,函数作为参数以及在数组中的应用

有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var sum = function(x, y) { return x + y; }, diff = function (x, y) { return x - y; }; var sumResult = calculator.calculate(2, 1, sum), diffResult = calculat

Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)...啊啊啊

函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. 而函数式编程(请注意多了一个"式"字)--Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算. 我们首先要搞明白计算机(Computer)和计算(Compute)的概念. 在计算机的层次上,CPU执行的是加减乘除的指令代码

函数二----函数的进阶

一.命名空间(有三种) 1.内置的命名空间   -----python解释器 就是python解释器一启动就可以使用的名字存储再内置的命名空间中 内置的名字在启动解释器的时候被加载进内存里. 2.全局命名空间    -----我们写的代码,但不是函数中的代码 是在程序从上到下被执行的过程中依次加载进内存的 放置了我们设置的所有变量名和函数名 3.局部命名空间   -----函数 就是函数内部定义的名字 当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了 三种命名空

Python_函数_内置函数02

Python的内置函数 zip()函数 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表. zip()示例 test = zip([1,2,3],[4,5,6]) print (test) # 结果为([1,4],[2,5],[3,6]) test1 = zip([1,2,3],[4,5,6,7]) print (test1) #

02 - 函数与装饰器

函数与装饰器 函数 概念 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数的返回值 return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式.不带参数值的return语句返回None. # return a,b,c等价于 return (a,b,c) def test(): a,b = 10,20 return a,b print(test()) 不定长参数传递 加了星号(*)的变量args会存放所有未命名的变量参数,args为元组; 而加**的变量kw

在线|二轮辅导[02][函数与初等函数习题]

广而告之 1.寒假下发的三套试题的答案已经上传,地址:地址: 2.为便于大家的网上学习,特开设博文用于收集大家的问题,博文地址:地址: 3.从第二次开始准备自己使用录屏软件在家录制:如果制作顺利,视频地址还会放在这一博文里面,请大家关注: 例题解析 例1[求复合函数的单调区间][2018天津模拟]已知函数\(y=f(x)(x\in R)\)的图像如图所示,则函数\(g(x)=f(log_ax)\)\((0<a<1)\)的单调递减区间为[] $A.[0,\cfrac{1}{2}]$ $B.[\s

09 匿名函数、函数作用域、闭包、递归

匿名函数(lambda) 语法规则: lambda 参数:表达式 filter(lambdax: x>10, li) 匿名函数:可以赋给一个变量,重复使用. fun1 = lambda x: x * 10 print(fun1(10)) 打印结果: 100 fun = (lambda x: x * 10)(5) print(fun) 打印结果: 50 函数作用域 01外部不能访问函数内部变量: def fun1(): x = 1 print(x) 02函数内部能够访问函数外部变量: x = 12

函数及函数优化

1. 函数构造方法: js中所有函数的构造函数都是Function,包括Function本身,(Function是自己的实例,也是自己的构造函数) 证明: Function.prototype === Function.__proto__ 1.1 函数声明: function 函数名(){} 1.2函数表达式: var 函数名 = function(){}; 1.3构造函数: var 函数名 = new Function(参数1,参数2,函数体); 1. 不传参数创建出来的是空函数. 2. 一个

MySQL高级查询函数(单行函数)

函数的分类:1,单行函数:对每一条记录输入值进行计算,得到相应的计算结果,返回给用户,也就是说,每条记录作为一个输入参数,经过函数计算得到每条记录的计算结果.2,多行函数:对多条记录输入值进行计算,得到多条记录对应的单个结果. 单行函数: ①:字符串函数(用户处理单行的字符数据,比如大小写转换,字符串截取,拼装等) a.LOWER/UPPER(LOWER(str):返回字符串str变为小写字母的字符串.UPPER(str):返回字符串str变为大写字母的字符串) SELECT UPPER(nam

C语言函数、函数指针解析

函数.函数指针的理解: 函数的定义: void myfunc(void) { } 函数的声明 void myfunc(void); 函数指针的定义.初始化.赋值: 定义:void (*funcp)(void); 初始化: void (*funcp)(void) = &myfunc; 赋值 void (*funcp)(void); funcp = &myfunc; 函数调用:(*funcp)(); funcp(); 也可以这样赋值:void (*funcp)(void); funcp = m