函数的三大器

news/2024/12/22 9:18:46/

 

迭代器

  1.函数名的使用以及第一类对象

  2.闭包

  3.迭代器

一.函数名的运用

  函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量

  1.函数名的内存地址

 

def func():print('呵呵')
print(func)

# 结果:
# <function func at 0x0000000000502E18>

 

  2.函数名可以赋值给其他变量

    

def func():print('呵呵')a = func
a()# 结果:
#  呵呵

  3.函数名可以当做容器类的元素

 

def func1():print('呵呵111')
def func2():print('呵呵222')
def func3():print('呵呵333')
def func4():print('呵呵444')li = [func1,func2,func3,func4]
for func in li:func()# 结果:
'''
呵呵111
呵呵222
呵呵333
呵呵444
'''

 

 

  4.函数名可以当做函数的参数

  

def func():print('你是谁?我是猪八戒啊')def fn(s):print('谁在我里面,谁在说话?')s()print('哇,不好了,连我也中招了')fn(func)#  结果
'''
谁在我里面,谁在说话?
你是谁?我是猪八戒啊
哇,不好了,连我也中招了
'''

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

  

def func():print('我是func ')def fn():print('我是fn')print('我是func')return fnfn = func()
fn()# 结果
'''
我是func 
我是func
我是fn'''

 

 二 .闭包

  什么是闭包?闭包就是内层函数,对外层函数(非全局) 的变量的引用

  

def fuc():name = 'hahage'def foo():print(name)foo()
fuc()
# 结果:
# hahage

 

  可以使用__closure__ 来检测函数是否是闭包,使用函数名 .__closure__ 返回 cell就是 闭包,返回None不是闭包

  

def func():name = '哈哈哥'def foo():print(name)foo()print(foo.__closure__)
func()# 结果:
# 哈哈哥
# (<cell at 0x00000000026F7D98: str object at 0x00000000021EAA50>,)

 

  问题 ---- 如何在函数外边调用内部函数呢?

def outer():name = '哈哈哥'def foo():print(name)return foo
foo = outer()  # 访问外部函数,获取到内部函数的函数地址
foo()          # 访问内部函数# 结果
# 哈哈哥

  那如果多层嵌套呢? 很简单 --- 只需要一层一层的往外层返回就行了

def func():def foo():def fn():print('嘿嘿嘿')return fnreturn foo
foo = func()
fn = foo()
fn()
# 结果
# 嘿嘿嘿

  由它可以引出闭包的好处,由于我们在外界可以访问内部函数,那这个时候内部函数访问的时间和时机就不一样了,因为在外部,在任意时间访问内部函数,这个时候,想一想,我们之前说过,如果一个函数执行完毕,则这个函数中的变量以及局部命名空间中的内容都将会被销毁,在闭包内,如果变量被销毁了,那内部的函数将不能正常执行,所以,python规定,如果你在内部函数中访问了外层函数的变量,那么这个变量将不会消亡,,,将会常驻内存中,也就是说,使用闭包,可以保证外层函数中的变量在内存中常驻,这样做有什么好处?非常大的好处,我们来看一个关于爬虫的代码:

from urllib.request import urlopen
def but():content = urlopen('http://www.521609.com/').read()def get_content():return contentreturn get_content
fn = but()
content = fn()
print(content)content2 = fn()
print(content2)

 

 

  综上; 闭包的作用就是让一个变量能够常驻内存,供后面的程序使用

  三 . 迭代器

    我们之前一直在用可迭代对象进行迭代操作,那么到底什么是可迭代对象,本小节主要讨论可迭代对象,首先我们先回顾一下目前我们所熟知的可迭代对象有哪些?

    str,list,tuple,dict,set ,那为什么我们可以称他们为可迭代对象呢?因为他们都遵循了可迭代协议,什么是可迭代协议?首先看一段代码

  

# 对的
s = 'abc'
for c in s:print(c)# 错的
for i in 123:print(i)
# 结果:
'''
a
b
c
Traceback (most recent call last):File "F:/爬虫/函数.py", line 28, in <module>for i in 123:
TypeError: 'int' object is not iterable
'''
 

 

 

  注意看报错信息中有这样一句话"'int' object is not iterable" 翻译过来就是整数类型对象是不可迭代的,iterable表示可迭代的,表示可迭代协议,那么如何进行验证你的数据类型是否符合可迭代协议,我们可以通过dir函数来查看类中定义好的所有方法

s = '我是哈哈哥'
print(dir(s))    # 打印对象中的方法和函数
print(dir(str))  # 打印类中声明的方法和函数'''
['__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'] ['__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']
'''

 

  在打印结果中,寻找 __iter__ 如果能找到,那么这个类的对象就是一个可迭代对象

  我们发现字符串中可以找到 __iter__ ,list,tuple,dict,set ,range 都有 __iter__ ,这几个数据类型同时也可以进行  for循环

  这是查看一个对象是否是可迭代对象的第一种办法,我们还可以通过 isinstence() 函数来查看对象是什么类型的

l = [1,2,3]
l_iter = l.__iter__()
from collections import Iterable
from collections import Iteratorprint(isinstance(l,Iterable))   # True
print(isinstance(l,Iterator))   # Falseprint(isinstance(l_iter,Iterable))  # True
print(isinstance(l_iter,Iterator))   # True

 

 

  综上 ----- 我们可以确定,如果对象中有 __iter__函数,那么我们认为这个对象遵循了 可迭代协议,就可以获取到相对应的迭代器,这里的 __iter__ 是帮帮助我们获取到对象的迭代器,我们使用迭代器中的 __next__( 来获取到一个迭代器中的元素,那么我们之前讲的 for 循环 的工作原理到底是什么,还是看下面的代码 ----------

 

s = '我是哈哈哥'
c = s.__iter__()    # 获取迭代器
print(c.__next__())  # 使用迭代器进行迭代 ,获取一个元素  我
print(c.__next__())  #
print(c.__next__())  #
print(c.__next__())  #
print(c.__next__())  #

  for 循环的机制 

  

for i in [1,2,3]:print(i)

  使用 while 循环 + 迭代器来模拟 for 循环

  

lst = [1,2,3]
lst_iter = lst.__iter__()while 1:try:i = lst_iter.__next__()print(i)except StopIteration:break

  总结:

    iterable:可迭代对象,内部包含 __iter__ () 函数

    iterator : 迭代器 -- 内部包含__iter__()  同时包含 __next__()  

    迭代器的特点:

      1.节省内存

      2.惰性机制

      3.不能反复,只能向下执行

  我们可以把要迭代的内容当成子弹,然后呢?获取到迭代器 __iter__( ),就是把子弹都装在弹夹中,然后发射就是 __next__() 把每一个子弹(元素)打出来,也就是说,for 循环的时候,一开始的时候是 __iter__()来获取迭代器,后面每次取元素都是通过 __next__()来完成的,当程序遇到StopIteration将结束循环

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

转载于:https://www.cnblogs.com/wenqi2121/p/11194404.html


http://www.ppmy.cn/news/450686.html

相关文章

Spring boot三大器

在Spring boot 中的应用中的三大拦截机制 Filter 、Interceptor 、Aspect 1、Filter Filter功能&#xff1a;可以拿到原始的http请求&#xff0c;但是拿不到你请求的控制器和请求控制器中的方法的信息 Filter使用&#xff1a; package com.llangzh.filter;import java.io.I…

python三大器_Python 入门之 Python三大器 之 迭代器

1、迭代器 (1)可迭代对象 <1> 只要具有__ iter__()方法就是一个可迭代对象 (我们可以通过dir()方法去判断一个对象具有什么方法&#xff0c;dir()会返回一个列表&#xff0c;这个列表中含有该对象的以字符串的形式的所有方法名) lst.__iter__() dict.__iter__() <2>…

java3大器_阿里祭出大器,Java代码检查插件

【套装3本】代码整洁之道三部曲教材 176.8元 包邮 (需用券) 去购买 > 背景 前阵子阿里巴巴发布了<>。 不久&#xff0c;又一气呵成发布了Eclipse/Intellij Idea下的代码检测插件PC3&#xff0c;可谓是国内代码优秀的检测插件。此插件检测的标准是根据<>上面制定…

windows pe文件导入表隐藏

前言 分析过一些文件&#xff0c;发现里面都会对引用的api进行动态获取&#xff0c;然后通过内存指针调用。细细想来&#xff0c;这种方法还是有一定的对抗作用的&#xff0c;如果别人想要分析的必须的稍微深入或者动态调试一下。然后&#xff0c;我就想着该如何实现这种用法呢…

python三大器,Python 入门之 Python三大器 之 生成器

Python 入门之 Python三大器 之 生成器 1、生成器 (1)什么是生成器&#xff1f; 核心&#xff1a;生成器的本质就是一个迭代器 迭代器是Python自带的 生成器程序员自己写的一种迭代器 def func(): print("这是一个函数") return "函数" func() def func():…

java三大器

拦截器&#xff1a;利用反射的机制实现&#xff0c;针对action、日志、未登录用户。 4.1&#xff0c;拦截器是基于java反射机制来实现的&#xff0c;而过滤器是基于函数回调来实现的。&#xff08;有人说&#xff0c;拦截器是基于动态代理来实现的&#xff09; 4.2&#xff0…

java 三大器

过滤器&#xff08;Filter&#xff09; 所谓过滤器顾名思义是用来过滤的&#xff0c;Java的过滤器能够为我们提供系统级别的过滤&#xff0c;也就是说&#xff0c;能过滤所有的web请求&#xff0c;这一点&#xff0c;是拦截器无法做到的。在Java Web中&#xff0c;你传入的requ…

python三大器_Python - 三大器 迭代器,生层器,装饰器

Python - 三大器 迭代器,生层器,装饰器 在介绍三大器之前先来了解一下容器和可迭代对象... 一. 容器 容器是一种把多个元素组织在一起的数据结构&#xff0c;容器中的元素可以逐个地迭代获取&#xff0c;可以用in, not in关键字判断元素是否包含在容器中。通常这类数据结构把所…