day10总结(2019-08-02)

1.匿名函数

匿名函数就是没有函数名的函数,属于function类型的数据,匿名函数本质还是函数,函数中除了声明语法以外,其他的都使用匿名函数
1)语法
lambda 参数列表:返回值
2)说明
lambda -- 关键字
参数列表 -- 参数名1,参数名2
: -- 固定
返回值 - 任何有结果的表达式;它匿名函数的函数体,相当于普通函数中的return语句
调用匿名函数: 保存匿名函数值的变量(实参列表)
3)参数
普通函数中除了用'参数名:类型'的形式来指定参数类型以外,其他的语法匿名函数都支持

2.全局变量和局部变量

1)全局变量
没有声明在函数内部和类里面的变量就是全局变量,作用域是从声明开始到文件结束的任何位置
2)局部变量
声明在函数中的变量就是局部变量(函数的参数相当于生命在函数中的位置),作用域从声明函数到函数结束的任何位置
3)函数的调用过程(内存):压栈
当调用函数的时候,系统会自动在内存的栈区间未这个函数开辟一个独立的内存区域,用来保存在函数中声明的变量,当函数调用结束后这个内存区域会自动释放。

a = 10   # 全局变量
# x是全局变量
for x in range(5):
    if False:
        c = 100
    b = 20   # 全局变量
    print('循环里面:', a)
    print('循环里面:', x)
print('外面:', b)
def func2(x1=10, y1=20):
    z1 = 100  # 内部变量
    print('函数内部:', x1, y1, z1)


func2()

3.global和nonlocal

global和nonlocal函数中的关键字,和return一样只能在函数体中使用
1)global - 在函数中声明一个全局变量
global 变量
变量 = 值

2)nonlocal: 在局部的局部中去修改局部变量的值
nonlocal 变量
变量 = 值

def func3():
    # 这儿是在声明一个局部变量a1
    a1 = 222
    print('函数里面a:', a1)

    # 这儿的b1是全局变量,改变了b1的局部变量
    global b1
    b1 = 333
    print('函数里面b:', b1)


func3()
```python
def func4():
    a2 = 100

    def func5():
                a2 = 500
        print('函数里面的函数里面a2:', a2)  # 500

    func5()

    print('函数里面a2:', a2)  # 100


func4()
def func4():
    a2 = 100
    nonlocal a2 
    def func5():
                a2 = 500
        print('函数里面的函数里面a2:', a2)  # 100

    func5()

    print('函数里面a2:', a2)  # 100

递归函数

"""
自己调自己的函数(函数体中调用当前函数)
循环能做的事情,递归都可以做

注意: 能用循环解决的问题就不要用递归
"""


# def func1():
#     print('=====')
#     func1()
#
#
# func1()

# 2.怎么写递归函数
"""
第一步: 找临界值(循环结束的条件) - 在这儿需要结束函数
第二步: 找关系 - 找f(n)和f(n-1)的关系(找当次循环和上次循环的关系)
第三步: 假设函数的功能已经实现,根据关系用f(n-1)去实现f(n)的功能
"""
# 用递归函数实现: 1+2+3+...+n
def sum1(n):
    # 第一步: 找临界值
    if n == 1:
        return 1
    # 第二步: sum1(n)和sum1(n-1)
    # sum1(n) == 1+2+3+...+n-1+n
    # sum1(n-1) == 1+2+3+ ... + n-1
    # sum1(n) = sum1(n-1) + n
    return sum1(n-1)+n


print(sum1(100))


# 用递归函数求斐波那契数列中第n个数: 1, 1, 2, 3, 5, 8, 13, 21,...
def sequence(n):
    if n == 1 or n == 2:
        return 1
    # 找关系:sequence(n)和sequence(n-1)
    # sequence(n) = sequence(n-1) + sequence(n-2)
    return sequence(n-1) + sequence(n-2)


print(sequence(1), sequence(2))
print(sequence(8))

迭代器(iterator)

迭代器作为容器可以保护多个数据,迭代器的数据来源:1)将其他序列转换成迭代器 2)生成器
1)将其他序列转换成迭代器

iter1 = iter('abc')
print(iter1, type(iter1))

iter2 = iter([12, 30, 90])
print(type(iter2))

获取迭代器中的元素
不管用哪种方式去获取了元素的值,那么这个元素在迭代器中就不存在了
1)获取单个元素:next(迭代器)、迭代器.next() -> 获取迭代器中的第一个元素

iter3 = iter('hello')
print(next(iter3))
print(next(iter3))
print(next(iter3))
print(iter3.__next__())

2)遍历:
for 变量 in 迭代器:
pass

iter4 = iter('world')
for x in iter4:
    print(x)

生成器(generator)

什么是生成器

1)生成器是迭代器中的一种
2)调用一个带有yield关键字的函数就可以得到一个生成器
如果一个函数中有yield关键字:
a.调用函数不会执行函数体
b.函数调用表达式的值不是函数的返回值,而是一个生成器对象

# 1.怎么去创建一个生成器
def func1():
    print('=======')
    if False:
        yield
    return 100


gen1 = func1()    # 这儿的gen1就是一个生成器对象
print('外部:', gen1)  # 外部: 

2.生成器产生数据的原理

1)一个生成器能够产生多少数据,就看执行完生成器对应的函数体会遇到几次yield;yield后面的值就是生成器能够产生的数据
2)每次获取生成器中的元素的时候,都是先去执行函数体,直到遇到yield,并且将yield后面的值作为获取元素的结果;并且保留结束的位置,下次获取下一个值的时候,从上次结束的位置接着执行函数体,直到遇到yield,如果从开始执行到函数结束都没有遇到yield,就会报StopIteration错误

def func2():
    print('+++++')
    yield 1
    print('-----')
    yield 100     # yield 后边可以跟数据;同一个函数可以有多个yield


gen2 = func2()
print(gen2)

print('函数外部:', next(gen2))
print('函数外部:', next(gen2))
# print('函数外部:', next(gen2))   # StopIteration
 写一个可以产生学号的生成器, 生成的时候可以自定制学号数字位的宽度和学号的开头
study_id_creater('py',5) -> 依次产生: 'py00001', 'py00002', 'py00003',....
   study_id_creater('test',3) -> 依次产生: 'test001', 'test002', 'test003',...
```python
def study_id_creater(str1, n):
    for i in range(1, 6):

        print(str1 + str(i).zfill(n))


study_id_creater('py', 5)
def study_id_creater(str1='abc', num=5):
    for i in range(1, num+1):
        yield str1 + str(i).zfill(7 - len(str1))


gen1 = study_id_creater()
print(next(gen1))
print(next(gen1))
print(next(gen1))
print(next(gen1))
print(next(gen1))

你可能感兴趣的:(day10总结(2019-08-02))