函数名的运用(第一类对象)以及闭包与迭代器

Posted rixian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数名的运用(第一类对象)以及闭包与迭代器相关的知识,希望对你有一定的参考价值。

一.函数名的应用(第一类对象)

1.函数的命名规范和变量是一样的,函数名其实就是变量名.

2.函数名的内存地址

def func():
    print("呵呵"

print(func)

结果:
<function func at 0x1101e4ea0>

 

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

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

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

结果:
<function func at 0x00000257861A6048>
呵呵
呵呵

 

4.可作为列表中的元素进行存储

def func1():

  pass

def func2():

  pass

lst = [func1,func2]

for el in lst:

  el()

def func1():
    print("我是1")
def func2():
    print("我是2")
def func3():
    print("我是3")

lst = [func1, func2, func3]
for el in lst:
    el()

结果:
我是1
我是2
我是3

 

5.可以作为参数传递给函数.

def fun():

  pass

def proxy(fu):

  fu()

proxy(func)

def func1():
    print("我是func1")
def func2():
    print("我是func2")
def func(fn, gn): # 函数名可以作为参数进行传递
    print("我是func")
    fn()
    gn()
    print("哈哈哈")
func(func1, func2)

结果:
我是func
我是func1
我是func2
哈哈哈

 

6.可以作为函数的返回值

def func():

  def inner():

    pass

  return inner

func()()

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

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

结果:
这里是函数1
这里是函数1
这里是函数2

 

二.闭包

1.闭包:在内层函数中访问外层函数的局部变量(内层函数,对外层函数(非全局)的变量的引用)

def func1():
    name = "alex"
    def func2():
        print(name)     # 闭包
    func2()
func1()

结果:
alex

 

2.我们可以使用__closure__来检测函数是否是闭包,使用函数名.__closure__返回None就不是闭包,返回其他内容就是闭包

def func1():
    name = "alex"
    def func2():
        print(name)     # 闭包
    func2()
    print(func2.__closure__)    # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,)
func1()

 

3.好处:

  (1).保护你的变量不受外界影响

  (2).可以让变量常驻内存

from urllib.request import urlopen

def outer():
    # 常驻内存
    s = urlopen("http://www.xiaohua100.cn/index.html").read()
    def getContent(): # 闭包
        return s
    return getContent

print("爬取内容.....")
pa = outer()     # 这个时候就开始加载校花100的内容
# 后面需要用到这里面的内容就不需要在执行非常耗时的网络连接操作了了
ret = pa()  # 获取内容 
print(ret)

ret = pa()  # 重新获取内容 
print(ret)

ret = pa()
print(ret)

ret = pa()
print(ret)

 

4.写法:

  def outer():

    a = 10

    def inner():

      print(a)

    return inner

5.在函数外调用内部函数

def outer():
    name = "alex"
    # 内部函数
    def inner():
        print(name)
    return inner

fn = outer()   # 访问外部函数, 获取到内部函数的函数地址
fn()    # 访问内部函数

 

6.如果为多层迭代,就一层一层返回

def func1():
    def func2():
        def func3():
                print("嘿嘿")
        return func3
    return func2

func1()()()

三.迭代器

1.我们熟知的迭代对象:str,list,tuple,dict,set;为什么我们可以称他们为可迭代对象?

因为他们都遵循了可迭代协议,那么什么是可迭代协议?先来看一段错误代码:

# 对的
s = "abc"
for c in s:
    print(c)

结果:
a
b
c

# 错的
for i in 123:
    print(i)

结果:
Traceback (most recent call last):
  File "F:/python/python kecheng/day12/code/04 闭包.py", line 77, in <module>
    for i in 123:
TypeError: ‘int‘ object is not iterable

 

注意:报错信息里有这么一句话: ‘int‘ object is not iterable ,翻译过来就是整数类型对象是不可迭代的,

iterable表示可迭代的,表示迭代协议,那么如何验证你的数据类型是否符号可迭代协议,我们可以通过dir

函数来实现查看

2.使用dir来查看该数据包含了哪些方法

3.用来遍历列表,字符串.元祖...可迭代对象

4.可迭代对象:Iterable,里面__iter__()可以获取迭代器,没有__next__()

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

通过dir函数发现,这几个可以进行for循环的东西都有__iter__函数,包括range也有

5.迭代器:Iterator,里面有__iter__()可以获取迭代器,还有__next__()

s = "岁月枯荣仿佛春秋一梦"
it = s.__iter__() # 获取迭代器
print(dir(it)) # 迭代器里有__iter__ 还有__next__

结果:
[__class__, __delattr__, __dir__, __doc__, __eq__, __format__, __ge__, __getattribute__, __gt__, __hash__, __init__, __init_subclass__, __iter__, __le__, __length_hint__, __lt__, __ne__, __new__, ‘__next__‘, __reduce__, __reduce_ex__, __repr__, __setattr__, __setstate__, __sizeof__, __str__, __subclasshook__]

6.查看一个对象是否为可迭代对象

(1).官方方案:

lst = ["赵四","刘能", "赵本山", "宋小宝"]
it = lst.__iter__()
from collections import Iterable    # 可迭代对象
from collections import Iterator    # 迭代器

print(isinstance(lst, Iterable))    #True
print(isinstance(lst, Iterator))    #False

print(isinstance(it, Iterable))     #True
print(isinstance(it, Iterator))     #True

 

(2).偏方

lst = ["暖春","炎夏","悲秋","寒冬"]

it = lst.__iter__()

# 偏方
print("__iter__" in dir(it))    #True
print("__next__" in dir(it))    #True
# 可以通过dir来判断数据是否是可迭代的, 以及数据是否是迭代器

 

6.迭代器的特点:

(1).只能向前

(2).惰性机制

(3).省内存(生成器)

s = "岁月枯荣仿佛春秋一梦"
it = s.__iter__() # 获取迭代器
# print(dir(it)) # 迭代器里有__iter__ 还有__next__
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())

 

7.for循环的内部机制

(1).首先获取到迭代器

(2).使用while循环获取数据

(3).it.__next__()来获取数据

(4).处理异常 try:xxx  except StopIteration:

语法:

it = xx.__iter__()

while 1:

  try:

    data = it.__next__()

    xxxxxx

  except StopIteration:

    break

# 迭代器模拟for循环
lst = ["娃哈哈", "乳娃娃", "爽歪歪", "小洋人","果粒橙"]
# for el in lst: # 底层用的是迭代器
#     print(el)

it = lst.__iter__() # 获取迭代器
while 1:
    try:    # 尝试执行
        el = it.__next__()  # 获取下一个元素
        print(el)
    except StopIteration:   # 处理错误
        break

使?用while循环+迭代器来模拟for循环(必须要掌握)

以上是关于函数名的运用(第一类对象)以及闭包与迭代器的主要内容,如果未能解决你的问题,请参考以下文章

第十一天 函数名的使用以及第一类对象, 闭包, 迭代器

python之路---11 第一类对象 函数名 闭包 迭代器

python之路---11 第一类对象 函数名 闭包 迭代器

python之函数名,闭包迭代器

python中的闭包,迭代器.

python 小兵迭代器