Python基础九函数进阶(二)

    回顾一下

函数名的本质就是函数的内存地址

1可以被引用

2可以当做容器类性的元素

3可以当做函数的参数和返回值

一、闭包

闭包的含义:内部函数引用外部作用域(非全局)的变量  (内部函数指的是函数内部定义的函数)

有与有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们有需求就是想拿到那怎么做呢?返回呀!
我们都知道函数内的变量我们想要在函数外不用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?

是不是直接就把这个函数名字返回就好了呢?

这才是闭包函数最常用的方法

def func():
    name = ‘eva‘
    def inner():
        print(name)
    return inner

f = func()
f()

判断闭包的方法__closure__

#输出的__closure__有cell元素 :是闭包函数
def func():
    name = ‘eva‘
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()
#输出的__closure__为None :不是闭包函数
name = ‘egon‘
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()

闭包嵌套

def wrapper():
    money = 1000
    def func():
        name = ‘eva‘
        def inner():
            print(name,money)
        return inner
    return func

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

爬虫里的闭包

from urllib.request import urlopen

def index():
    url = "https://www.cnblogs.com/gzying-01/"
    def get():
        return urlopen(url).read()
    return get

xiaohua = index()
content = xiaohua()
print(content.decode(‘utf-8‘))  # 解码中文显示

二、迭代器

  1、首先什么是可迭代对象?

字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

那我们如何来证明呢?上代码:

from collections import Iterable

l = [1,2,3,4]
t = (1,2,3,4)
d = {1:2,3:4}
s = {1,2,3,4}                

print(isinstance(l,Iterable)) # 返回bool值
print(isinstance(t,Iterable))
print(isinstance(d,Iterable))
print(isinstance(s,Iterable))

#返回结果True
True
True
True

  2、可迭代协议

我们现在是从结果分析原因,能被for循环的就是“可迭代的”,但是for怎么知道谁是可迭代的?

假如我们自己写了一个数据类型,希望这个数据类型里的东西可以被使用for循环一个个取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__inter__方法

print(dir([1,2]))
print(dir((2,3)))
print(dir({1:2}))
print(dir({1,2}))

结果:
[‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__delitem__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__gt__‘, ‘__hash__‘, ‘__iadd__‘, ‘__imul__‘, ‘__init__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mul__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__reversed__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__setitem__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘append‘, ‘clear‘, ‘copy‘, ‘count‘, ‘extend‘, ‘index‘, ‘insert‘, ‘pop‘, ‘remove‘, ‘reverse‘, ‘sort‘]
[‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__getnewargs__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mul__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘count‘, ‘index‘]
[‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__delitem__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__setitem__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘clear‘, ‘copy‘, ‘fromkeys‘, ‘get‘, ‘items‘, ‘keys‘, ‘pop‘, ‘popitem‘, ‘setdefault‘, ‘update‘, ‘values‘]
[‘__and__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__iand__‘, ‘__init__‘, ‘__ior__‘, ‘__isub__‘, ‘__iter__‘, ‘__ixor__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__ne__‘, ‘__new__‘, ‘__or__‘, ‘__rand__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__ror__‘, ‘__rsub__‘, ‘__rxor__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__sub__‘, ‘__subclasshook__‘, ‘__xor__‘, ‘add‘, ‘clear‘, ‘copy‘, ‘difference‘, ‘difference_update‘, ‘discard‘, ‘intersection‘, ‘intersection_update‘, ‘isdisjoint‘, ‘issubset‘, ‘issuperset‘, ‘pop‘, ‘remove‘, ‘symmetric_difference‘, ‘symmetric_difference_update‘, ‘union‘, ‘update‘]

验证结果

总结一下现在我们所知道的:可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法。

接着分析,__iter__方法做了啥事儿?

可迭代的:内部必须含有一个__iter__方法。

  3、迭代器

什么叫做迭代器?迭代器英文叫做iterator。

l = [1,2,3,4]
l_iter = l.__iter__()  # 将可迭代的转化成迭代器
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)

迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

for循环,能遍历一个可迭代对象,他的内部到底进行了什么?

将可迭代对象转化成迭代器。(可迭代对象.__iter__())

内部使用了__next__方法,一个一个取值。

交了 异常处理功能,取值到底自动停止。

用为了循环模拟for循环:

l = [1,2,3,4]
l_iter = l.__iter__()
while True:
    try:
        item = l_iter.__next__()
        print(item)
    except StopIteration:
        break

  4、为什么要有for循环?

给予上面的一大堆遍历方法,貌似看上去就可以满足我们的遍历需求了,为何还要搞一个叫做for的玩意儿?

=[1,2,3]

index=0
while index < len(l):
    print(l[index])
    index+=1

#要毛线for循环,要毛线可迭代,要毛线迭代器

没错,序列类型字符串,列表,元组都有下标,用上述方法遍历,确实看上去很完美。但是如果遇到非序列类型的比如字典,集合,文件句柄这些家伙,是不是就不灵了。所以,for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,而且你看到的效果也确实如此,这就是无所不能的for循环,最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存~

原文地址:https://www.cnblogs.com/gzying-01/p/10208767.html

时间: 2024-08-29 19:35:33

Python基础九函数进阶(二)的相关文章

Python基础九函数进阶(一)

Q:Python运行代码时,遇到函数是怎么做到的? A:从Python解释器开始执行之后,就在内存中开辟一个空间,每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读入内存,表示知道这个函数存在了,至于函数内部的变量跟逻辑,解释器根本不关心. 当执行到函数调用的时候,Python解释器会再开辟一块内存来存储这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中,函数中的变量只能在函数内部使用

python基础_函数进阶

函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式 无参数,无返回值 无参数,有返回值 有参数,无返回值 有参数,有返回值 定义函数时,是否接收参数,或者是否返回结果,是根据 实际的功能需求 来决定的! 如果函数 内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部 如果希望一个函数 执行完成后,向外界汇报执行结果,就可以增加函数的返回值

Python基础—初识函数(二)

1.给函数参数增加元信息 写好一个函数,然后想为这个函数的参数增加一些额外的信息,这样的话其他使用者就能清楚的知道这个函数应该怎么使用. 使用函数参数注解是一个很好的办法,它能提示程序员应该怎样正确使用这个函数. 例如,下面有一个被注解了的函数: def add(x:int, y:int) -> int: return x + y python解释器不会对这些注解添加任何的语义.它们不会被类型检查,运行时跟没有加注解之前的效果也没有任何差距. 然而,对于那些阅读源码的人来讲就很有帮助啦.第三方

python基础之函数进阶之函数作为返回值/装饰器

因为装饰器需要用到返回函数的知识,所以在这里将返回函数和装饰器合并讲解. 什么是返回函数? 我们知道,一个函数中return可以返回一个或者多个值,但其实,return不仅可以返回值,还可以返回函数. 实例: def col(*arg): def sum(): res_sum=0 for i in arg: res_sum=res_sum+i return res_sum return sum a=col(1,2,3,4,5) print(a)<function col.<locals>

python基础之函数进阶

装饰器 s1.pydef outer(func): def inner(): print("before") func() print("after") return inner @outer def f1(): print("F1") s2.pyimport s1s1.f1() #输出 before F1 after 装饰器格式 @+函数 功能 1 自动执行outer函数并且将下面的函数名f1当作参数传递 2 将outer函数的返回值,重新赋值

python基础——sorted()函数

python基础——sorted()函数 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来. Python内置的sorted()函数就可以对list进行排序: >>> sorted([36, 5, -12, 9, -21]) [-21, -12, 5, 9, 36] 此外,sorted()函数也是一个

Python基础07 函数

Python基础07 函数 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 函数最重要的目的是方便我们重复使用相同的一段程序. 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句. 函数的定义 首先,我们要定义一个函数, 以说明这个函数的功能. def square_sum(a,b): c = a**2 + b**2 return c 这个函数的功能是求两个数的平方和. 首先

python基础——匿名函数及递归函数

python基础--匿名函数及递归函数 1 匿名函数语法 匿名函数lambda x: x * x实际上就是: def f(x): return x * x 关键字lambda表示匿名函数,冒号前面的x表示函数参数. 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果. 2 匿名函数举例 用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突.此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数: >>> f = lam

python基础教程函数参数

python里有很多的内置函数给我们的工作带来了很多发便利,在我们实现某些功能或者优化代码的时候,可以自己定义一个函数,同时我们在定义一个类的时候也会用到函数的一些知识去构造一个方法,这里就涉及到一些关于函数的基础知识和函数传参的知识. 一.函数的相关介绍 1.函数定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可. 函数特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 2.函数的定义示例 定义一个函数要使用def语句,依次写出函数名.括