011-2018-09-17 迭代器和闭包

1.今日内容大纲

一. 上节课内容回顾
    1. 函数: 对功能或者动作的封装
        定义:
            def 函数名(形参列表):
               函数体(return)
            调用:
                函数名(实参列表)
            形参: 在函数声明的位置写的变量
                1. 位置参数
                2. 默认值参数
                3. 动态传参:
                    1. *args 位置参数的动态传参, 接收的是元组
                    2. **kwargs 关键字的动态传参, 接收的是字典
                    *和** 在形参表示聚合, 在实参表示打散
            实参: 在函数调用的时候给形参传递的值
                1. 位置参数
                2. 关键字参数
                3. 混合参数
            传参: 把实参传递给形参的过程

            返回值:
                1. 不写return或者只写return return None
                2. return 值 返回一个值
                3. return 值1, 值2, 值3. 返回多个值. 元组

            名称空间:
                1. 内置名称空间. python解释器提供的内置的东西
                2. 全局名称空间. 全局变量. 全局函数
                3. 局部名称空间. 局部变量. 在函数内部

            作用域:
                1. 全局作用域
                2. 局部作用域

            globals() 查看全局作用域中的内容
            locals() 查看当前作用域中的内容

            global 把全局变量引入进来
            nonlocal 在局部, 把离他最近的上一层的变量引入进来

二. 作业讲解
三. 今日主要内容
    1. 函数名第一类对象
        函数名其实就是变量名
        1. 可以像变量一样互相赋值.
        2. 可以作为函数的参数,进行传递
        3. 可以作为返回值返回
        4. 可以作为集合的元素进行存储

    2. 闭包(函数的嵌套. 返回函数名)
        作用:
            1. 保护变量
            2. 常驻内存
        基本写法
            def outer():
                a = 10
                def inner():
                    return a
                return inner

    3. 迭代器(用)
        1. Iterable:  可迭代的.里面有__iter__()
        2. Iterator:  迭代器. 里面有__iter__() 还有 __next__()

        特点:
            1. 节省内存(欠)
            2. 惰性机制(只有执行__next__()才会取值)
            3. 只能向前. 不能反复

        dir() 查看数据可以执行的方法
        isinstance() 判断xxx对象是否是xxx类型

        for循环的内部用的是迭代器
        lst = [1, 2, 3]
        it = lst.__iter__().__next__()
        while 1:
            try:
                it.__next__()
            except StopIteration:
                break

    预习:
        1. 生成器函数
        2. 推导式
        3. 生成器表达式

2.练习

'''
day10作业及默写
1,继续整理函数相关知识点,写博客。

2,写函数,接收n个数字,求这些参数数字的和。(动态传参)

3,读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么?
	a=10
	b=20
	def test5(a,b):
     		print(a,b)
	c = test5(b,a)
	print(c)

4,读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么?
	a=10
	b=20
	def test5(a,b):
		a=3
		b=5
     	print(a,b)
	c = test5(b,a)
	print(c)
	print(a,b)
5,写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等),将每个实参的每个元素依次添加到函数的动态参数args里面.
例如 传入函数两个参数[1,2,3] (22,33)最终args为(1,2,3,22,33)

6,写函数,传入函数中多个实参(实参均为字典),将每个实参的键值对依次添加到函数的动态参数kwargs里面.
例如 传入函数两个参数{‘name’:’alex’} {‘age’:1000}最终kwargs为{‘name’:’alex’ ,‘age’:1000}
7, 下面代码成立么?如果不成立为什么报错?怎么解决?
7.1
	a = 2
	def wrapper():
    	    print(a)
	wrapper()

7.2
	a = 2
	def wrapper():
            	a += 1
    		print(a)
	wrapper()
7.3
def wrapper():
    		a = 1
    		def inner():
        		print(a)
    		inner()
	wrapper()
7.4
def wrapper():
    		a = 1
    		def inner():
        		a += 1
        		print(a)
    		inner()
	wrapper()

8,写函数,接收两个数字参数,将较小的数字返回.

9,写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接,形成新的字符串,并返回.
例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’

10,写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}
例如:min_max(2,5,7,8,4) 返回:{‘max’:8,’min’:2}(此题用到max(),min()内置函数)

11,写函数,传入一个参数n,返回n的阶乘
例如:cal(7)  计算7*6*5*4*3*2*1

12写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃’,‘A’)]

13 有如下函数:
def wrapper():
    		def inner():
        		print(666)
	wrapper()

你可以任意添加代码,用两种或以上的方法,执行inner函数.


14相关面试题(先从纸上写好答案,然后在运行):
1,有函数定义如下:
def calc(a,b,c,d=1,e=2):
return (a+b)*(c-d)+e
请分别写出下列标号代码的输出结果,如果出错请写出Error。
print(calc(1,2,3,4,5))_____
print(calc(1,2))____
print(calc(e=4,c=5,a=2,b=3))___
print(calc(1,2,3))_____
print(calc(1,2,3,e=4))____
print(calc(1,2,3,d=5,4))_____

2,(此题有坑)下面代码打印的结果分别是_________,________,________.
def extendList(val,list=[]):
    	list.append(val)
    	return list
	list1 = extendList(10)
	list2 = extendList(123,[])
	list3 = extendList('a')

	print('list1=%s'%list1)
	print('list2=%s'%list2)
	print('list3=%s'%list3)


	3, 写代码完成99乘法表.(升级题)
1 * 1 = 1
2 * 1 = 2 2 * 2 = 4
3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
......
9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81

作业写完了的同学继续完善昨天的作业。

明日默写:
	1,形参的接收顺序。
	2,什么是命名空间,什么是全局名称空间,什么是局部名称空间,什么是内置名称空间。
	3,什么是全局作用域,什么是局部作用域。
	4,名称空间的加载顺序,取值顺序。
	5,解释一下什么是global,什么是nonlocal。

'''

# 写函数,接收n个数字,求这些参数数字的和。(动态传参)
def func(*n):
    sum = 0
    for el in n:
        sum += el
    return sum

ret = func(1,2,5,4,7)


# 写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等),
# 将每个实参的每个元素依次添加到函数的动态参数args里面.
# 例如 传入函数两个参数[1,2,3] (22,33)最终args为(1,2,3,22,33)

# def func(*args): # str, list, tuple, set
#     print(args)
#     # lst = []
#     # for el in args:
#     #     for e in el:
#     #         lst.append(e)
#     # tu = tuple(lst)
#     # print(tu)
#
# func(*"哈哈", *[1,3,5], *(456,789))


# 写函数,传入函数中多个实参(实参均为字典),将每个实参的键值对依次添加到函数的动态参数kwargs里面.
# 例如 传入函数两个参数{‘name’:’alex’} {‘age’:1000}最终kwargs为{‘name’:’alex’ ,‘age’:1000}
# def func(**kwargs):
#     print(kwargs)
#
# func(**{"alex": "大帅逼", "wusir":"丑"})



# 9,写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接,形成新的字符串,并返回.
# 例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’
# def func(it):
#     # result = ""
#     # for el in it:
#     #     result += str(el) + "_"
#     # return result[:-1]
#     for i in range(len(it)):
#         el = str(it[i])
#         it[i] = el
#     return "_".join(it)
#
# print(func([1,"alex","wusiar"]))
# print("alex"+213)


# 写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}
# 例如:min_max(2,5,7,8,4) 返回:{‘max’:8,’min’:2}(此题用到max(),min()内置函数)

# def func(*n):
#     return {"最大值":max(n), "最小值":min(n)}
#
# print(func(1,8,6,4,5,15,63,35,5))


# 求阶乘
# def func(n):
#     sum = 1
#     for i in range(n, 0, -1):
#         sum *= i
#     return sum
# print(func(5))



# 写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
# 例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃’,‘A’)]

# 花色:红黑芳草
# 点数: A2345678910
# 笛卡儿积.
# def func():
#     hua = ["红心", "黑桃", "梅花", "方块"]
#     dian = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
#     result = []
#     for huase in hua:
#         for dianshu in dian:
#             result.append((huase, dianshu))
#     return result
#
#
# def wrapper():
#     def inner():
#         print(666)
#
#     return inner # 函数名可以作为变量返回
#
#
# fn = wrapper()
# fn()

# def extendList(val, list=[]): # 默认值在内存中只会产生一份
#     list.append(val)
#     return list
#
# list1 = extendList(10)
# print('list1=%s' % list1)
# list2 = extendList(123, [])
# print('list2=%s' % list2)
# list3 = extendList('a')
# print('list3=%s' % list3)
#
# print(id(list1))
# print(id(list3))
# print(id(list2))


# 写代码完成99乘法表.(升级题)
# 1 * 1 = 1
# 2 * 1 = 2 2 * 2 = 4
# 3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
# ......
# 9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81
#
# for i in range(1, 10):
#     for j in range(1, i+1):
#         print("%s x %s = %s" % (i, j, i*j), end=" ")
#     print() # 换行
#
#       *
#      ***
#     *****
#    *******
#   *********
#  ***********
#   *********
#    *******
#     *****
#      ***
#       *

3.函数的应用

# def chi():
#     print("吃月饼")
# print(chi)
# fn = chi # 函数名可以进行赋值
# a = 10
# b = a
# chi()
# fn()
# 函数名可以像变量名一样进行使用


# def func1():
#     print("我是一个单纯的函数")
#
# def func2(abc): # abc接收到的是一个函数的内存地址
#     abc()  # 执行func1, func1()
#     print("我是func2", abc)
#
# # a = "苹果"
#
# func2(func1) # func1是函数的内存地址, 函数名可以像变量一样进行参数的传递


# def outer():
#     def inner():
#         print("我是里面")
#     return inner
#
# outer()() # ()表示的是执行
# ret = outer() # outer得到的结果是inner
# ret() # 执行的是inner函数

# a = "周润发"
# b = "蓝洁瑛"
# c = "春三十娘"
# d = "简直了"
#
# lst = [a, b, c, d]
# for el in lst:
#     print(el)

# def chi():
#     print("吃饭")
# def he():
#     print("喝饮料")
# def du():
#     print("赌是不好的")
# def chou():
#     print("少抽点烟")
#
# lst = [chi, he, du, chou]
# for el in lst:
#     el()

# a = 10
# print(a + 20)

# 错误的
# def a():
#     pass
# print(a + 10)
#
# def panpan():
#     print("我是潘潘. 我喜欢毒丈夫 ")
#
# def xiaoping():
#     print("我是小萍萍. 我喜欢毒丈夫 ")
#
# def xiaohua():
#     print("我是小花花. 我喜欢毒丈夫 ")
#
# def daguanren():
#     print("大官人喜欢xxxx")
#
# def wangpo(nv, nan): # 核心业务逻辑
#     nv()
#     nan()
#
# wangpo(xiaohua, daguanren) # 王婆代理了大官人和潘潘


# def chi():
#     print("我是吃")
#
# a = chi
# haha = a
# hehe = haha
# bilibili= hehe
#
# bilibili()
# print(bilibili.__name__) # 函数名

def play(wanjv1, wanjv2, wanjv3):
    '''
        玩儿函数
        :param wanjv1: 玩具1
        :param wanjv2: 玩具2
        :param wanjv3: 玩具3
        :return: 开心
    '''
    print("我要玩儿荡秋千")
    return "开心"


# play("独木桥", "独轮车", "独眼龙")
print(play.__doc__) #  document
print(str.join.__doc__)

4.闭包

# def func():
#     a = 10
#     print(a)
# func()
# print(a) # 在外面你是访问不到局部变量的, 局部变量是安全的


# 全局变量可能会被修改, 全局变量是不安全的. 可能会被其他函数所更改
# a = 10
# def func():
#     global a
#     a = 20
#     print(a)
# func()
# print(a)

# 用闭包可以保护我们的变量
# 写法: 在外层函数中声明一个变量. 在内层函数使用或者返回这个变量.
# 这个结构叫闭包
# 1.可以保护我的变量
# 2.可以让一个变量常驻内存

# def outer():
#     a = 10 # 常驻内存
#     def inner():
#         print(a) # 在内部使用的外面的变量
#     return inner # 返回了内部函数
#
#
# # ret是inner的地址. ret就是inner
# ret = outer()
# # ret() # 这里执行inner()
# # print("哈哈")
# # print("哈哈")
# # print("哈哈")
# # ret() # inner的执行时间是不确定的
# # print("哈哈")
# # print("哈哈")
# # print("哈哈")
# # ret() # inner的执行时间是不确定的
#
# # def haha():
# #     pass
# # print(ret.__closure__) # 有东西, 就是闭包. None就不是闭包

# 闭包的应用.保护变量, 常驻内存
from urllib.request import urlopen

def func():
    # 闭包. content会常驻内存
    content = urlopen("http://www.xiaohuar.com/").read()
    def inner():
        return content
    return inner

print("加载中...")
g = func() # 网络请求
print("加载完毕")
print(g())
print(g())
print(g())











5.迭代器

# for c in 123:
#     print(c)


# iterable 可迭代的, str, list. tuple, dict, set, open(), range()
# dir() 可以查看某数据类型中可以执行的方法
# s = "alex"
# print(dir(s)) # 在字符串中发现了__iter__. 没有__next__
# a = 123
# print(dir(a)) # 在int中没有__iter__ 没有__next__
# lst = [1, 2, 3,]
# print(dir(lst)) # 在list中也有__iter__

# 所有包含了__iter__的东西都可以使用for循环. 都可以进行迭代
# 迭代器, 在for循环内部. 调用了__iter__(), 访问__iter__()可以得到迭代器
# lst = [1, 2, 3, 4, 5, 6]
#
# it = lst.__iter__()  # iterator 迭代器
# while 1:
#     try:
#         print(it.__next__())
#     except StopIteration:
#         print("结束了")
#         break

# for el in lst:
#     print(el)
# else:
#     print("结束了")


# 迭代器给所有的数据类型提供了一种统一的遍历的方式(可迭代协议), Iterable, __iter__()
# lst = [1, 2, 3, 4, 5]
# # print("__iter__" in dir(lst))
# # print("__next__" in dir(lst))
#
# it = lst.__iter__()
# # print("__iter__" in dir(it)) #  迭代器里面是有__iter__的.  迭代器一定是可迭代的
# # print("__next__" in dir(it))
#
# for el in it: # 迭代器可以使用for循环
#     print(el)

# 小总结
# Iterable: 可迭代对象. 里面包含了__iter__(),可以使用for循环
# Iterator: 迭代器. 里面包含了__iter__() 和 __next__(), 也可以使用for循环

# from collections import Iterable # 可迭代的
# from collections import Iterator # 迭代器
#
# lst = ["周润发","麻花藤","刘伟"]
# print(isinstance(lst, Iterable)) # instance  实例, 对象
# print(isinstance(lst, Iterator)) # instance  实例, 对象
#
# it = lst.__iter__()
# print(isinstance(it, Iterable)) # instance  实例, 对象
# print(isinstance(it, Iterator)) # instance  实例, 对象

#  总结
#  特点:
#   1. 节省内存
#   2. 惰性机制
#   3. 只能向前. 不能反复

lst = [1,2,3]
it = lst.__iter__()
print(it.__next__())
print(it.__next__())
print(it.__next__())

# 重新拿一个迭代器
it = lst.__iter__()
print(it.__next__())
print(it.__next__())
print(it.__next__())



6.其他


def func():
    print("我是太阳. 早晚会爆炸")

func = "武大郎"

print(func)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值