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. SSHD

    SSH基本概述 SSH服务协议说明 SSH 是 Secure Shell Protocol 的简写,由 IETF 网络工作小组(Network Working Group )制定在进行数据传输之前,S ...

  2. 你的首个golang语言详细入门教程 | your first golang tutorial

    本文首发于个人博客https://kezunlin.me/post/a0fb7f06/,欢迎阅读最新内容! your first golang tutorial go tutorial version ...

  3. 多线程六 同步容器&并发容器

    同步容器(使用的是synchronized,并且不一定是百分百安全) 本篇续 -- 线程之间的通信 ,介绍java提供的并发集合,既然正确的使用wait和notify比较困难,java平台为我们提供了 ...

  4. 【解决】MySQL提示启动成功,实际进程并没有起来

    一.概括: 1.查看运行日志 vim /var/log/mariadb/mariadb.log 2.修改配置文件 vim /etc/my.cnf 3.修改文件权限 chown mysql.mysql ...

  5. ASP.NET Core 2.2 WebApi 系列【六】泛型仓储模式

    为什么要使用泛型仓储?好处是? 前两章在autofac注入的时候,用的User类作为例子,写了增删改查四个接口,也就是仓储的GRUD. 当我们再添加一个实体(比如Student)时,StudentRe ...

  6. ASP.NET MVC IOC依赖注入之Autofac系列(一)- MVC当中应用

    话不多说,直入主题看我们的解决方案结构: 分别对上面的工程进行简单的说明: 1.TianYa.DotNetShare.Model:为demo的实体层 2.TianYa.DotNetShare.Repo ...

  7. Selenium(一):原理与安装、简单的使用

    1. selenium原理 1.1 selenium介绍 Selenium是一个Web应用的自动化框架. 通过它,我们可以写出自动化程序,像人一样在浏览器里操作web界面. 比如点击界面按钮,在文本框 ...

  8. js的try catch使用心得

      1 try catch的使用,永远应该放在你的控制范围之内,而不应该防范未知的错误.也就是说你很清楚知道这里是有可能”出错“的,而且你很清楚知道什么前提下会出错,你就是要故意利用报错信息来区分错误 ...

  9. vue小案例--简易评论区

    一.小案例(评论区) 1.流程 (1)分析静态页面.(vue项目创建参考https://www.cnblogs.com/l-y-h/p/11241503.html)(2)拆分静态页面,变成一个个组件. ...

  10. echarts玩转图表之矩形树图

    前言 这是第一次用makedown编辑器写文章,感觉像一件利器,排版美观而且效率飙升.进入正题 Echart官网文档地址 针对于矩形树图api配置项链接 1. 完全从数据定义图形 $.get( &qu ...