1. 函数名的运用

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

1.1 函数名的内存地址

def func():
  print("呵呵")
  print(func)

结果:
<function func at 0x1101e4ea0>

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

def func():
  print("呵呵")
print(func)

a = func # 把函数当成⼀个变量赋值给另⼀个变量
a() # 函数调⽤ func()

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

def func1():
  print("呵呵")
def func2():
  print("呵呵")
def func3():
  print("呵呵")
def func4():
  print("呵呵")
lst = [func1, func2, func3]
for i in lst:
  i()

1.4 函数名可以当做函数的参数

def func():
  print("吃了么")
def func2(fn):
  print("我是func2")
  fn() # 执⾏传递过来的fn
  print("我是func2")

func2(func) # 把函数func当成参数传递给func2的参数fn.

1.5 函数名可以作为函数的返回值

def func_1():
  print("这⾥是函数1")
  def func_2():
    print("这⾥是函数2")
  print("这⾥是函数1")
  return func_2

fn = func_1() # 执⾏函数1. 函数1返回的是函数2, 这时fn指向的就是上⾯函数2
fn() # 执⾏上⾯返回的函数

2. 闭包

什么是闭包? 闭包就是内层函数,对外层函数(非全局)的变量的引⽤,叫闭包。
def func1():
  name = "alex"
  def func2():
    print(name) # 闭包
  func2()
func1()

结果:
alex
我们可以使⽤__closure__来检测函数是否是闭包,使⽤函数名.__closure__返回cell就是闭包,返回None就不是闭包。
def func1():
  name = "alex"
  def func2():
    print(name) # 闭包
  func2()
  print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at0x10c3fc650>,)
func1()
问题,如何在函数外边调⽤内部函数呢?
def outer():
  name = "alex"
  # 内部函数
  def inner():
    print(name)
  return inner

fn = outer() # 访问外部函数, 获取到内部函数的函数地址
fn() # 访问内部函数
那如果多层嵌套呢? 很简单,只需要⼀层⼀层的往外层返回就⾏了。
def func1():
  def func2():
    def func3():
      print("嘿嘿")
    return func3
  return func2

func1()()()
由它我们可以引出闭包的好处,由于我们在外界可以访问内部函数,那这个时候内部函
数访问的时间和时机就不⼀定了。因为在外部,我可以选择在任意的时间去访问内部函数。这
个时候,想⼀想,我们之前说过,如果⼀个函数执⾏完毕,则这个函数中的变量以及局部命名
空间中的内容都将会被销毁。在闭包中,如果变量被销毁了,那内部函数将不能正常执⾏,所
以,python规定,如果你在内部函数中访问了外层函数中的变量,那么这个变量将不会消亡,
将会常驻在内存中。也就是说,使⽤闭包,可以保证外层函数中的变量在内存中常驻,这样做
有什么好处呢? 非常⼤的好处,我们来看⼀个关于爬⾍的代码:
from urllib.request import urlopen
def but():
  content = urlopen("http://www.xiaohua100.cn/index.html").read()
  def get_content():
    return content
  return get_content
fn = but() # 这个时候就开始加载校花100的内容
# 后⾯需要⽤到这⾥⾯的内容就不需要在执⾏⾮常耗时的⽹络连接操作了
content = fn() # 获取内容
print(content)

content2 = fn() # 重新获取内容
print(content2)
综上,闭包的作⽤就是让⼀个变量能够常驻内存,供后⾯的程序使⽤。

3. 迭代器

我们之前⼀直在⽤可迭代对象进⾏迭代操作,那么到底什么是可迭代对象。本⼩节主要讨
论可迭代对象,⾸先我们先回顾⼀下⽬前我们所熟知的可迭代对象有哪些:
str, list, tuple, dict, set. 那为什么我们可以称他们为可迭代对象呢? 因为他们都遵循了可
迭代协议,什么是可迭代协议,⾸先我们先看⼀段错误代码:
# 对的
s = "abc"
for c in s:
  print(c)
# 错的
for i in 123:
  print(i)

结果:
Traceback (most recent call last):
   File "/Users/sylar/PycharmProjects/oldboy/iterator.py", line 8, 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)) # 也可以打印类中声明的⽅法和函数
在打印结果中,寻找__iter__ 如果能找到,那么这个类的对象就是⼀个可迭代对象。
['__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__,继续看⼀下list, tuple, dict, set。
print(dir(tuple))
print(dir(list))
print(dir(open("护⼠少妇嫩模.txt"))) # ⽂件对象
print(dir(set))
print(dir(dict))
结果:
['__add__', '__class__', '__contains__', '__delattr__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count',
'index']
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
'__init_subclass__', '__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']
['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__',
'__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__',
'__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__',
'__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed',
'_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing',
'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno',
'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read',
'readable', 'readline', 'readlines', 'seek', 'seekable', 'tell',
'truncate', 'writable', 'write', 'writelines']
['__and__', '__class__', '__contains__', '__delattr__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__iand__', '__init__', '__init_subclass__', '__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']
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__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']
我们发现这⼏个可以进⾏for循环的东⻄都有__iter__函数,包括range也有,可以⾃⼰试⼀下,这是查看⼀个对象是否是可迭代对象的第⼀种办法,我们还可以通过isinstence()函数来查看⼀个对象是什么类型的。
l = [1,2,3]
l_iter = l.__iter__()
from collections import Iterable
from collections import Iterator
print(isinstance(l,Iterable)) #True
print(isinstance(l,Iterator)) #False
print(isinstance(l_iter,Iterator)) #True
print(isinstance(l_iter,Iterable)) #True
综上,我们可以确定,如果对象中有__iter__函数,那么我们认为这个对象遵守了可迭代协议,就可以获取到相应的迭代器。这⾥的__iter__是帮助我们获取到对象的迭代器,我们使⽤迭代
器中的__next__()来获取到⼀个迭代器中的元素,那么我们之前讲的for的⼯作原理到底是什么? 继续看代码。
s = "我爱北京天安⻔"
c = s.__iter__() # 获取迭代器
print(c.__next__()) # 使⽤迭代器进⾏迭代. 获取⼀个元素 我
print(c.__next__()) # 爱
print(c.__next__()) # 北
print(c.__next__()) # 京
print(c.__next__()) # 天
print(c.__next__()) # 安
print(c.__next__()) # ⻔
print(c.__next__()) # StopIteration
for循环的机制:
for i in [1,2,3]:
  print(i)
使⽤while循环+迭代器来模拟for循环(必须要掌握)
lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
  try:
    i = lst_iter.__next__()
    print(i)
  except StopIteration:
    break
总结:
Iterable: 可迭代对象,内部包含__iter__()函数。
Iterator: 迭代器,内部包含__iter__() 同时包含__next__()。
迭代器的特点:
1. 节省内存
2. 惰性机制
3. 不能反复, 只能向下执⾏
我们可以把要迭代的内容当成⼦弹,然后呢,获取到迭代器__iter__(),就把⼦弹都装在弹夹中,然后发射就是__next__()把每⼀个⼦弹(元素)打出来。也就是说,for循环的时候,⼀开始的
时候是__iter__()来获取迭代器,后⾯每次获取元素都是通过__next__()来完成的,当程序遇到StopIteration将结束循环。

python基础(13):函数名的使用、第一类对象、闭包、迭代器的更多相关文章

  1. python 函数名的应用(第一类对象),闭包,迭代器

    1.函数名的应用(第一类对象) 函数名的命名规范和变量是一样的 函数名其实就是变量名 可以作为列表中的元素进行储存. def func1(): pass def func2(): pass lst = ...

  2. 巨蟒python全栈开发-第11天 第一类对象 闭包 迭代器

    一.今日主要内容总览(重点) 1.第一类对象->函数名=>变量名 (1)函数对象可以像变量一样进行赋值 (2)还可以作为列表的元素进行使用 (3)还可以作为返回值返回 (4)还可以作为参数 ...

  3. Python_Mix*函数名的使用以及第一类对象,闭包,迭代器,for循环的内部机制

    一:函数名的应用(第一类对象) 函数名的命名规范和变量是一样的,函数名其实就是变量名, 0)函数名可以赋值给其他变量 def func(): #定义一个名为func的函数 print('my ange ...

  4. python 第一类对象 闭包 迭代器

    ########################总结########################### 1. 函数名 -> 第一类对象 函数名就是变量名. 函数可以赋值 函数可以作为集合类的 ...

  5. Python基础之 函数名,闭包,和迭代器

    1.函数名作用 函数名本质上就是函数的内存地址或对象. 1.可以被引用 2.可以被当作容器类型的元素 3.可以当作函数的参数和返回值 4.如果记不住的话,那就记住一句话,就当普通变量用 2.闭包 什么 ...

  6. python基础之函数名的使用,闭包以及迭代器

    内容梗概: 1. 函数名的使⽤用以及第⼀一类对象 2. 闭包 3. 迭代器 1.函数名一. 函数名的运⽤.函数名是一个变量, 但它是⼀个特殊的变量, 与括号配合可以执行函数的变量.1.1 函数名的内存 ...

  7. 第4章 基础知识进阶 第4.1节 Python基础概念之迭代、可迭代对象、迭代器

    第四章 基础知识进阶第十七节 迭代.可迭代对象.迭代器 一.    引言 本来计划讲完元组和字典后就讲列表解析和字典解析,但要理解列表解析和字典解析,就需要掌握Python的高级的类型迭代器,因此本节 ...

  8. python第一类对象,闭包,迭代器

    一.第一类对象 第一类对象 -> 函数名 -> 变量名 1.特征:     函数对象可以像变量一样进行赋值     还可以作为列表的元素进行使用     还可以作为返回值返回     还可 ...

  9. day11 第一类对象 闭包 迭代器

    今日主要内容: 1 . 第一类对象 -->函数名--> 变量名 2. 闭包 -->函数的嵌套 3. 迭代器 --> 固定的思想 for 循环 第一类对象  : 函数对象介意向变 ...

随机推荐

  1. Java连接数据库 #07# MyBatis Generator简单例子

    MyBatis Generator是一个可以帮助我们免去手写实体类&接口类以及XML的代码自动生成工具. 下面,通过一个简单的例子介绍MyBatis Generator如何使用. 大体流程如下 ...

  2. SpringBoot整合Thymeleaf表单更新操作

    对于表单值回显并更新的逻辑相比大家都已经很熟悉了, 但是我们操作Thymeleaf的话这里就会有一点小坑了, 在要回显值的表单的所有字段上,我们都要加上 th:field,才可以完成回显值更新 或者这 ...

  3. Slickflow.NET 开源工作流引擎高级开发(六) -- WebTest 引擎接口模拟测试工具集

    前言:引擎组件的接口测试不光是程序测试人员使用,而且也是产品负责人员需要用到的功能,因为在每一步流转过程中,就会完整模拟实际用户发生的场景,也就容易排查具体是程序问题还是业务问题,从而快速定位问题,及 ...

  4. JavaWeb问题记录——在Windows上启动Tomcat后命令行窗口乱码

    JavaWeb问题记录——在Windows上启动Tomcat后命令行窗口乱码 摘要:本文主要记录了在Windows上启动Tomcat后,命令行窗口出现乱码的问题及解决办法. 问题重现 在Windows ...

  5. Java中的“浅复制”与“深复制”

    复制 将一个对象的引用复制给另一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅复制,第三种方式是深复制. 1.直接赋值 在Java中,A a1 = a2,这实际上复制的是引用,也就是说 ...

  6. 怎么将CAD转PNG格式?这两种方法值得收藏

    在从事相关CAD工作的小伙伴们都知道,CAD中不光需要绘制各种各样的图纸,还需要根据工作的需要来进行图纸格式的转换工作.那有的时候就需要将CAD转换成PNG格式的图片进行使用.那怎么将CAD转PNG格 ...

  7. ABP入门教程3 - 解决方案

    点这里进入ABP入门教程目录 创建项目 点这里进入ABP启动模板 如图操作,我们先生成一个基于.NET Core的MPA(多页面应用).点击"Create my project!" ...

  8. 高级语言——java

    高级语言——java 起源与发展 1991 年,James Gosling 博士发布产品 Oak,这是 Java 语言的前身. 1995 年,Oak 语言改名为 Java. 1996 年,JDK(Ja ...

  9. jmeter使用问题——数据库无法连接

    使用Jmeter 数据库连接配置组件,执行sql时jmeter日志报错 WARN o.a.j.p.j.p.AbstractJDBCProcessor: SQL Problem in 查询账号申诉ID: ...

  10. Mysql 如何创建一张临时表

    mysql 利用 temporary 关键字就可以创建出一个临时表.创建的这张表会在与服务器的会话终止时自动消失 语法:create temporary table tbl_name...; 规则:每 ...