关于函数的默认值与python闭包以及迭代器

# 在函数中如果默认值参数是一个可变的数据类型, 如果有人调用的时候改变了他. 其他位置看到的也跟着改变了
def fn(val,list=[]):
    list.append(val)
    return list

print(fn(5))
# 这个位置我们给val传值了打印的结果一定是[5]

print(fn(6))

# 这个位置我们继续传值发现结果是[5, 6],那么也就是说函数中参数的默认值是同一个,而不是每次调用函数生产新的默认值
# # 在函数中如果默认值参数是一个可变的数据类型, 如果有人调用的时候改变了他. 其他位置看到的也跟着改变了
# def fn(val,list=[]):
#     list.append(val)
#     return list
#
# print(fn(5))
# # 这个位置我们给val传值了打印的结果一定是[5]
#
# print(fn(6))

# 这个位置我们继续传值发现结果是[5, 6],那么也就是说函数中参数的默认值是同一个,而不是每次调用函数生产新的默认值



# 什么是闭包以及闭包实际作用
# 我们知道函数声明的时候是不执行的,只有在调用的时候才会在内存开辟空间,python内部的垃圾回收机制,会在函数执行完毕后回收这块内存

def fn1():
    val = 100
    print(val)
fn1()
# 这个时候在执行完fn1后,它所在的那块内存就会被清空,而闭包的作用就是可以让这块内存常驻

def fn2():
    val  = 100
    def fn3():
        return val
    print(fn1.__closure__)
    print(fn2.__closure__)
    print(fn3.__closure__)
    return fn3
print(fn2()())

# 可以用__closure__函数来检测是不是闭包
# None
# None
# (<cell at 0x000001366E928B28: int object at 0x00007FFAD5407D60>,) fn3的结果是闭包


# 在python中srt,list,tuple,dict,set,file这些都属于可迭代对象,那么他们为什么是可迭代对象呢,因为它们遵循了可迭代协议

s = "真相定论"
# print(dir(s))
# ['__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', 'isascii', '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__这个就是迭代器,而拥有迭代器的则是可迭代对象`

# print(dir(s.__iter__()))
# ['__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__']
# 当我们执行它获取迭代器时,发现迭代器中也含有iter也是可迭代对象

itr = s.__iter__()
# 获取迭代器
print(itr.__next__())
print(itr.__next__())
print(itr.__next__())
print(itr.__next__())
#
# # 相
# # 定
# # 论
#  分别打印出了四个字

lst = [1,2,3,4,5]

itr2 = lst.__iter__()

print(itr2.__next__())
print(itr2.__next__())
print(itr2.__next__())
print(itr2.__next__())
print(itr2.__next__())

# 获取lst的迭代器并且利用nextAPI实现了手动迭代
# 用while模拟一下迭代器
while 1:
    try:
        name = itr2.__next__()
        print(name)
    except StopIteration:
        break
# try跟js中的容错机制差不多


# 还用一种判断是否为迭代器的方法
from collections.abc import Iterable
from collections.abc import Iterator

print(isinstance(itr,Iterable))
print(isinstance(itr,Iterator))

# True
# True
# 两个True所以itr即是迭代器又是可迭代对象

print(isinstance(lst,Iterable))
print(isinstance(lst,Iterator))

# lst是可迭代对象但不是迭代器

 

posted on 2019-10-14 13:30  素心~  阅读(145)  评论(0编辑  收藏  举报

导航