美文网首页
python函数进阶——函数名,闭包,迭代器

python函数进阶——函数名,闭包,迭代器

作者: hiDaLao | 来源:发表于2018-08-21 15:23 被阅读19次

函数名的应用


我们都知道,函数名的命名规则与变量基本相同,那么函数名可以做那些事呢?

首先,函数是通过 函数名()调用的,那么如果直接输出函数名会是什么情况呢?

def func():
    return 666
print(func())
print(func)
666
<function func at 0x0000021AC539AD90>

  可以看到,如果直接输出函数名,那么打印的是函数在内存中的地址,所以函数名的第一个用法是:
  函数名表示函数的内存地址

同时,函数名不仅命名方式与变量相同,函数名还可以直接当作变量使用
见以下代码:

def func1():
    return 666
c = func
c()
666

  不仅如此,函数名还可以作为函数的参数以及返回值
  见下:

def func2(a):
    print(a)
    return a()
    
def func3():
    print(666)

func2(func3)
<function func3 at 0x0000021AC4785158>
666

  最后,函数名还可以作为容器类类型的元素

a = 6
b = 4
c = 6
l = [a,c,c]
print(l)

def func4():
    print(666)

def func5():
    print(777)

def func6():
    print(888)
l1 = [func4,func5,func6]
for i in l1:
    i()
    
    
[6, 6, 6]
666
777
888

  以上便是函数名的应用,总结一下,函数名共有以下作用:

  • 函数名可以表示函数的内存地址
  • 函数名可以作为变量使用
  • 函数名可以作为函数的参数和返回值
  • 函数名可以作为容器类类型的元素

闭包


  什么是函数的闭包?首先是首先让我们看看维基百科中关于闭包的概念:

  在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性
  通过这个定义,我们可以得出函数中形成闭包需要满足以下条件:

  • 必须要有函数的嵌套
  • 内层函数必须要引用外层函数中的变量(不能是全局变量)
  • 外层函数必须返回内部函数的引用
def func():     #定义一个外部函数
    x = 10
    def func7():     #定义一个内部函数
        nonlocal x
        x += 1      #内部函数中引用外部函数
        return x
    return func7    #外部函数返回内部函数

f = func()          # f = func7
print(f())
print(f())
print(f())
print(x)
11
12
13



---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-27-0478bb8088ab> in <module>()
     11 print(f())
     12 print(f())
---> 13 print(x)


NameError: name 'x' is not defined

  那么闭包有什么作用呢?

   当程序执行时,遇到了函数执行,他会在内存中开辟一个空间,局部名称空间,如果这个函数内部形成了闭包,那么他就不会随着函数的结束而消失。

   something more:closure方法

  闭包函数相对于普通函数会多出一个closure属性里面定义了一个元组用于存放所有的cell对象,每个cell对象一一保存了这个闭包中所有的外部变量。

def func8():
    pass
print(func8.__closure__)

def func9():
    i = 10
    j = 'yang'
    def func10():
        print(i,j)
    print(func10.__closure__)
    return func10
l = func9()
l()
None
(<cell at 0x0000021AC5447EB8: int object at 0x0000000056A96200>, <cell at 0x0000021AC5447498: str object at 0x0000021AC5471F10>)
10 yang

可迭代对象和迭代器


首先抛出结论:

  • 可迭代对象包含迭代器。
  • 如果一个对象拥有iter方法,其是可迭代对象;如果一个对象拥有next方法,其是迭代器。
  • 定义可迭代对象,必须实现iter方法;定义迭代器,必须实现iter和next方法。

  在介绍迭代器之前,我们先来回顾一下之前提到的一个名词:可迭代对象(iterable)
  在之前的的介绍中,我们知道字符串、列表、字典等都是可迭代对象,我们可以对可迭代对象进行for循环,如下:

s = '123'
li = [1,2,3]
dic = {1:2,2:3,3:4}
for i in s:
    print(i)
for i in li:
    print(i)
for i in dic:
    print(i)
for i in 123:             #报错信息提示:'int' object is not iterable int型不可迭代
    print(i)
1
2
3
1
2
3
1
2
3



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-36-9241d29cd0b3> in <module>()
      8 for i in dic:
      9     print(i)
---> 10 for i in 123:
     11     print(i)


TypeError: 'int' object is not iterable

那么,究竟什么是可迭代对象呢?在理解这个概念之前,我们必须先了解一个方法:__iter__
对象内部含有__iter__方法就是可迭代对象.我们通过代码来验证:

a = 123
s = '123'
l = [1,2,3]
dic = {1:2,2:3,3:4}
print('__iter__' in dir(a))          #dir方法可以获得调用对象的所有属性和方法
print('__iter__' in dir(s))
print('__iter__' in dir(l))
print('__iter__' in dir(dic))
False
True
True
True

判断对象是不是可迭代对象的方法除了iter方法外,还有isinstance方法:

from collections import Iterable
print(isinstance(a,Iterable))
print(isinstance(s,Iterable))
print(isinstance(l,Iterable))
print(isinstance(dic,Iterable))
False
True
True
True

  那么什么是迭代器呢?在最开始的结论中我们提到,迭代器属于可迭代对象,但比可迭代对象多了一个__next__方法,那么问题来了,what's __next__方法?手动黑人问号脸
  最常见的迭代器是文件句柄,见下:

f = open('register', encoding='utf-8')
print('__iter__' in dir(f))
print('__next__' in dir(f))
print('__iter__' in dir(dict))
print('__next__' in dir(dict))
True
True
True
False

那么__next__方法如何使用呢?每next一次,取一次值

print(f.__next__())
print(f.__next__())
yang|123

jin|456

可迭代对象与迭代器的区别:

  • 可迭代对象不能取值,迭代器是可以取值的。(不借助索引或key等方法)
  • 迭代器非常节省内存。
  • 迭代器每次只会取一个值。
  • 迭代器单向的,一条路走到头。
    可迭代对象是可以通过__iter__()转为迭代器的
lis = [1, 2, 3]  # 可迭代对象
ite1 = lis.__iter__()  # 迭代器  <list_iterator object at 0x0000027A183BFFD0>
ite1 = iter(lis)  # 迭代器  <list_iterator object at 0x0000027A183BFFD0>
print(ite1)
<list_iterator object at 0x0000021AC5499588>

for循环对可迭代对象进行遍历的背后实现原理:

  1. 将可迭代对象转化成迭代器。
  2. 调用__next__方法取值。
  3. 利用异常处理停止报错。

while 1:
    try:
        print(ite1.__next__())
    except StopIteration:
        break
1
2
3

相关文章

  • python函数进阶——函数名,闭包,迭代器

    函数名的应用 我们都知道,函数名的命名规则与变量基本相同,那么函数名可以做那些事呢? 首先,函数是通过 函数名()...

  • Python装饰器-专题笔记

    学会装饰器,Python更进阶 函数作用域到闭包到装饰器讲解,及闭包和装饰器的运用。 [√] 慕课网Meshare...

  • Lua语言学习教程

    lua闭包 函数尾调用 迭代器

  • Python基础11-函数2(装饰器)

    装饰器 1.1 作用: 在函数名以及函数体不被改变的的前提下,给函数附加一些额外的操作代码 综合能力高阶函数闭包函...

  • Python - 2017/01/28-函数

    调用python内置函数 函数名(参数) 即可调用python内置函数 help(函数名) 返回python对于函...

  • 5、迭代器实现

    闭包实现迭代器 迭代函数实现迭代器 --1,调用迭代函数,(把状态变量和控制变量当做参数传递给迭代函数) 状态变...

  • 函数

    本节学习几种函数 匿名函数 高阶函数 闭包 头等函数的作用 匿名函数 什么是匿名函数? 通俗的讲就是没有函数名的函...

  • Python第四天(函数高级)

    python闭包: 装饰器:所谓的装饰器,就是不改变原来的函数,再对原函数进行其他的输出操作定义一个原函数的装饰函...

  • python之理解闭包和装饰器

    python之理解闭包和装饰器 1、闭包函数 1.1 python中函数都是对象 结果: 上面定义一个shut函数...

  • day2-python3函数

    今天练习了python3的各类型函数。包括: 基本语法 高级函数 递归 生成器与迭代器 闭包与装饰器 练习题代码实...

网友评论

      本文标题:python函数进阶——函数名,闭包,迭代器

      本文链接:https://www.haomeiwen.com/subject/pkkjiftx.html