DAY11 函数进阶(函数名的本质,闭包,迭代器)

函数名的本质与一级对象:

  1.函数名表示函数的内存地址。

  2.函数名可以赋值给变量,可以作为容器数据类型的元素。

  3.函数名可以作为参数传递给函数。

  4.函数名可以作为函数的返回值。

#一。 函数名表示函数的内存地址
def func():
    print(111)
print(func)
>>><function func at 0x00000199DFD22F28>

#二。函数名可以赋值给变量,可以作为容器数据类型的元素。

def func():
    print(111)
f = func      #2.函数名可以赋值给一个变量
f()
>>>
111

def foo1():
    print(1)
def foo2():
    print(2)
def foo3():
    print(3)
def foo4():
    print(4)

l1 = [foo1,foo2,foo3,foo4] #3.函数名可以当做容器类数据类型的元素
for i in l1:
    i()
>>>
1
2
3
4

#三。函数名可以作为参数传递给函数
def fun1():
    print(222)
def func2(x):
    x()
func2(fun1)
>>>
222

#四。函数名可以作为函数的返回值
def func1(x):
    return x
def func2():
    print(‘in the func2‘)
res = func1(func2)
res()

闭包:

  内部函数对外部作用域(非全局作用域)的变量的引用,并返回。该内部函数称为闭包函数。

#这是闭包
def wrapper(x):
    def inner():
        print(x)
    inner()
wrapper(‘he‘)
>>>
‘he‘

#这是闭包
name = ‘he‘
def wrapper(n):
    def inner():
        print(n)
    return inner()
wrapper(name)

##这不是闭包
name = ‘he‘
def wrapper():
    def inner():
        print(name)     #因为引用了全局作用域的变量
    return inner()
wrapper()

  判断一个内部函数是不是闭包有一个好方法:"__closure__"

  (1)如果__closure__有cell为闭包函数

  (2)如果__closure__返回的是None,则不是闭包函数。

# 这是闭包,返回有cell就是闭包
def func():
    name = ‘he‘
    def inner():
        print(name)
    print(inner.__closure__)
    inner()
func()
>>>
(<cell at 0x00000183451865E8: str object at 0x0000018345217810>,)
he

#这不是闭包,因为返回的是None
name = ‘he‘
def wrapper():
    def inner():
        print(name)
    print(inner.__closure__)
    inner()
wrapper()
>>>
None
he

  闭包的作用:

  # 回顾前面的知识,python解释器遇到一个函数的执行就会开辟一块新的内存空间,然后随着函数的执行结束,这块内存空间会被释放掉。但是如果一个函数被多次调用,就得多次创建内存,然后释放,再创建,再释放。。。这样对内存的损害很大

  # 但是,python解释器有一个机制,一旦检测到你的内层是一个闭包,它会在内存中开辟一块新的空间,这个空间不会随着函数的结束而释放。起到了保护内存的作用。

  闭包的嵌套:

‘‘‘闭包嵌套‘‘‘
def wrapper():
    money = 1000
    def func():
        name = ‘he‘
        def inner():
            print(name + ‘ have ‘ + str(money))
        return inner
    return func

f = wrapper()
i = f()
i()

可迭代对象(iterable)与可迭代器(iterator)

一. 可迭代对象

  前提:在python中,可以理解成一切皆对象。

  可迭代对象:(1)对象内部含有"__iter__"方法,就是可迭代对象。

        (2)可迭代对象满足可迭代协议。

#回顾我们学过的可迭代对象:str,list,tuple,dict,set,range()
# dir(obj) 方法:返回一个对象的所有方法

s1 = ‘str‘
print(dir(s1))    #返回了字符串的所有方法
>>>
[‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__getnewargs__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mod__‘, ‘__mul__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__rmod__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘capitalize‘, ‘casefold‘, ‘center‘, ‘count‘, ‘encode‘, ‘endswith‘, ‘expandtabs‘, ‘find‘, ‘format‘, ‘format_map‘, ‘index‘, ‘isalnum‘, ‘isalpha‘, ‘isdecimal‘, ‘isdigit‘, ‘isidentifier‘, ‘islower‘, ‘isnumeric‘, ‘isprintable‘, ‘isspace‘, ‘istitle‘, ‘isupper‘, ‘join‘, ‘ljust‘, ‘lower‘, ‘lstrip‘, ‘maketrans‘, ‘partition‘, ‘replace‘, ‘rfind‘, ‘rindex‘, ‘rjust‘, ‘rpartition‘, ‘rsplit‘, ‘rstrip‘, ‘split‘, ‘splitlines‘, ‘startswith‘, ‘strip‘, ‘swapcase‘, ‘title‘, ‘translate‘, ‘upper‘, ‘zfill‘]

  怎么判断一个对象是否为可迭代对象:

  (1)判断方法"__iter__"是否在对象的方法中,因可迭代对象都含有‘__iter__‘

  (2)通过isinstance(obj,type)来判读,返回True/False

     from collection  import  Iterable

     isinstance(obj,Iterabel)

# 方法一:通过对象是否含有‘__iter__’方法
dic = {‘name‘:‘he‘,‘age‘:23}
print(‘__iter__‘ in dir(dic))
>>>
True

# 方法二:通过isinstance()方法判断

from collections import Iterable
dic = {‘name‘:‘he‘,‘age‘:23}
print(isinstance(dic,Iterable))
>>>
True

二.迭代器(Iterator)

  迭代器:对象内部既含有"__iter__"又含有"__next__"方法的就是迭代器。

  判断一个对象是否为迭代器:

  (1)这个对象的方法中是否含有‘__iter__‘和‘__next__‘

  (2)通过isinstace(obj,type)来判断

#我们接触过得迭代器有:文件句柄

# 方法一:判断对象的方法中是否同时含有"__iter__"和"__next__"
f = open(r‘E:\python_training_s1\day9\register.txt‘,encoding=‘utf-8‘)
print(‘__iter__‘ in dir(f))
print(‘__next__‘ in dir(f))
f.close()
>>>
True
True

#方法二:使用isinstance(obj,Iterator),返回True/False

from collections import Iterator
f = open(r‘E:\python_training_s1\day9\register.txt‘,encoding=‘utf-8‘)
print(isinstance(f,Iterator))
f.close()
>>>
True

  

三.可迭代对象VS迭代器

  (1)可迭代对象与迭代器有什么不同?

    1.可迭代对象不能取值(之所以能取,是python中作了优化),迭代器能够取值。

    2.迭代器非常节省内存,每次只会取一个值,在内存中只占一个内存空间。

    3.迭代器是单向的,不能够反复。

  (2)可迭代对象转换成迭代器,iterable.__iter__()

l1 = [1,2,3] #可迭代对象
iter_l1 = l1.__iter__()  #迭代器 iter(iterable_obj)
print(iter_l1,type(iter_l1))

print(iter_l1.__next__())
print(iter_l1.__next__())
print(iter_l1.__next__())

   (3)for循环的内部原理

    1.将可迭代对象转换为迭代器。

    2.调用__next__方法取值

    3.利用异常处理停止报错

# 使用while循环重现for循环的原理

s1 = ‘abcd‘
iter1 = s1.__iter__()
while 1:
    try:
        print(iter1.__next__())
    except Exception:
        break

  

 

  

原文地址:https://www.cnblogs.com/hebbhao/p/9493634.html

时间: 2024-10-07 16:28:48

DAY11 函数进阶(函数名的本质,闭包,迭代器)的相关文章

Python 全栈开发:python函数进阶

python函数进阶 函数嵌套 函数对象 命名空间与作用域 闭包函数 装饰器 一.函数嵌套 函数的嵌套定义 def func1(): print('from func1') def func2(): #func2=内存地址 print('from func2') print(func2) func1() 函数的嵌套调用 # 比较两个数的大小 def max2(x,y): if x > y: return x else: return y # 比较三个数的大小 def max3(x,y,z): r

函数—函数进阶(二)

函数-函数进阶(二) 函数-函数进阶-列表生成式 1 #列表回顾 2 name = [2,5,7,9,4] 3 print(name) 4 for i in name: 5 print(i) 6 #结果为: 7 # [2, 5, 7, 9, 4] 8 # 2 9 # 5 10 # 7 11 # 9 12 # 4 13 14 #枚举 15 for index,i in enumerate(name): 16 print(index,i) 17 #结果为: 18 # 0 2 19 # 1 5 20

函数进阶知识整理

闭包函数 把函数A和变量x包在函数B内部,然后通过函数B的返回值返回出函数A对象 def outter(x): x = 1 def inner(): print(x) return inner f = outter(1) f() f() f() # 查看闭包的元素 print(F"f.__closure__[0].cell_contents: {f.__closure__[0].cell_contents}") 1 1 1 f.__closure__[0].cell_contents:

python开发函数进阶:命名空间,作用域,函数的本质,闭包,内置方法(globales)

一,命名空间 #局部命名空间#全局命名空间#内置命名空间 #三者的顺序#加载顺序 硬盘上--内存里#内置-->全局(从上到下顺序加载进来的)-->局部(调用的时候加载) 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 #全局命名空间 5 a = 5 6 b = 8 7 #局部命名空间(函数) 8 def my_max(): 9 c = a if a > b else b 10 return c 11 m = my_max() 12 pr

函数名的本质和闭包

函数名的本质: 函数可以作为容器中一项 函数名可以赋值 可以作为参数 可以做返回值 返回值的本质:是返回的值,而不是某个变量 def func(): a=1 return  a b=func() print(b) func#函数的内存地址 函数名加括号==调用 函数地址加括号==调用 函数名可以赋值 def  f(): print(123) f() a=b=f f() a() b=() 容器类型:列表 元祖 字典 集合 函数可以作为容器类型中的一项,可以做字典的keys def f1(): pr

函数进阶------闭包函数

1,命名空间: 定义:存放名字与值的绑定关系. 一个分为三种:全部命名空间,局部命名空间,内置命名空间. 内置命名空间:就是python为我们内置的一些可以直接拿来用的方法. 三种空间的加载顺序:内置命名空间(程序加载前)---全局命名空间(从上到下的顺序)----局部命名空间(调用的时候才开辟的空间) 2:作用域 定义:作用域就是作用范围 分为2中:内置名称空间和全局名称空间 3:globals:把局部名称空间的转化成全局名称空间,但是在所有的高级语言中, 都不常用,没到不得已的时候不要用.

函数进阶——闭包,装饰器,生成器,迭代器

闭包 函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问他们所在的外部函数中声明的所有局部变量.参数.当其中一个这样的内部函数在包含他们的外部函数之外被调用时,就会形成闭包. 装饰器 在不修改原函数的情况下,给原函数增加新的功能,使得程序变得可扩展 http://www.cnblogs.com/alex3714/articles/5765046.html(转) 列表生成式 1 a = [i+1 for i in range(10)] 2 print(a)#[1,

函数进阶之闭包函数和装饰器

闭包函数 把函数A和变量x包在函数B内部,然后通过函数B的返回值返回除函数A对象 def B(x): # x = 1 def A(): print(x) pass return A 装饰器 用来给函数加功能,他的本质也是函数 1.不改变被装饰函数的源代码 2.不改变被装饰函数的调用方式 def outter(func): def wrapper(*args,**kwargs): #逻辑 res = func(*args,**kwargs) # func是被装饰的函数 return res ret

scala成长之路(7)函数进阶——可能是史上最浅显易懂的闭包教程

由于scala中函数内部能定义函数,且函数能作为函数的返回值,那么问题来了,当返回的函数使用了外层函数的局部变量时,会发生什么呢?没错,就产生是闭包. 关于闭包的解释网上一大堆,但基本上都是照葫芦画瓢,一个模子刻出来的,说来说去都只讲了"内部函数引用外层函数的局部变量"这个刻板的定义,根本没降到精髓.精髓是什么?且看我一句话给你讲清楚: 闭包就是外层函数函数的对象,外层函数就是闭包的构造函数! 怎么样,是不是摸不着头脑?其实是这样,我们使用闭包的目的并不是为了引用外层函数的局部变量,这