小白学习Python的第十二天

一. 有参装饰器

有参装饰器的功能 - 在给函数添加功能的时候可以通过参数控制具体的操作(操作不固定)
2.怎么写有参装饰器

"""
def 函数名0(装饰器的参数列表):
    def 函数名1(func):
        def 函数名2(*args, **kwargs):
            result = func(*args, **kwargs)
            新功能
            return result
        return 函数名2
    return 函数名1


def 函数名(装饰器的参数列表):
    无参装饰器
    return 无参装饰器的函数名


有参装饰器的用法:
@函数名0(装饰器实参列表)
"""
# 写一个装饰器可以在函数结束后打印指定的任意提示信息
def add_message(msg):
    def test1(func):
        def new_func(*args, **kwargs):
            result = func(*args, **kwargs)
            print(msg)
            return result
        return new_func
    return test1


@add_message('结束')
def func1(x, y):
    print(x+y)


func1(10, 20)
# 练习:写一个装饰器,在原函数返回值的基础上减去指定的值
# @sub(10)   @sub(30)


def sub(num):
    def test2(func):
        def new_func(*args, **kwargs):
            result = func(*args, **kwargs)
            if type(result) in (int, float, bool, complex):
                return result-num
            return result
        return new_func
    return test2


@sub(20)
def func2(x, y):
    return x*y


print(func2(10, 20))

二. 迭代器

1.什么是迭代器(iter)

"""
迭代器是容器型数据类型(序列),
特点:a.不能同时查看所有元素(打印看不到里面的元素)
     b.不能统计个数
     c.获取元素的时候只能一个一个的取(每次取最上层的那个),每次获取元素该元素就会从迭代器中消失(取一个就少一个)

"""

2.创建迭代器对象

"""
迭代器创建有两种方式
1)通过iter将其他序列转换成迭代器
2)创建生成器
"""
iter1 = iter([10, 20, 30, 40])
print(iter1)   # <list_iterator object at 0x000001BC01F4B198>
# print(len(iter1))   # TypeError: object of type 'list_iterator' has no len()

3.获取元素
不管通过什么样的方式获取到了迭代器中的元素,对应的元素都会从迭代器中消失

"""
1)取单个元素
next(迭代器) - 获取迭代器最上面的一个数据(如果迭代器为空,就会报StopIteration错误)

2)遍历
for 遍历 in 迭代器:
    pass
"""
print(next(iter1))   # 10
print(next(iter1))   # 20
next(iter1)          # 30
print(next(iter1))   # 40
# print(next(iter1))   # StopIteration

iter2 = iter('hello')
for i in iter2:
    print(i)

iter3 = iter('python!')
list1 = list(iter3)
print(next(iter3))   # StopIteration

iter4 = iter('python123')
next(iter4)
for i in iter4:
    print('i', i)

三. 生成器

1.什么是生成器(generator)

"""
生成器的本质就是迭代器(迭代器的特点和获取元素的方式生成器都适用)
"""

2.怎么创建生成器

"""
调用一个带有yield关键字的函数就可以创建一个生成器对象
(如果被调用的函数里面有yield,不会执行函数体也不会获取函数返回值)
"""
def func1():
    print('=====')
    print('+++++')
    yield
    return 100


re = func1()
print(re)   # <generator object func1 at 0x0000020B004BBBF8>

3.怎么确定生成器中产生的数据

"""
产生数据的个数:看执行完生成器对应的函数的函数体会遇到几次yield
产生的数据的值:看每次遇到的yield后面的数据是什么,没有数据就是None
"""
def func2():
    yield 100
    yield 'abc'
    for i in range(3):
        yield i


gen1 = func2()
# print(gen1)

# print(len(gen1))   # TypeError: object of type 'generator' has no len()
# print(len(list(gen1)))   # 5
print(list(gen1))   # [100, 'abc', 0, 1, 2]

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

"""
调用函数创建生成器对象的时候不会执行函数体,获取生成器中的元素的时候才会执行。
第一次获取元素会从函数体开始的位置开始执行,执行到第一次yield就停下来,并且将yield后面的数据作为这次获取到的元素。
后面每次获取元素的时候都是从上次结束的位置接着往后执行,执行到下一次yield又会停下来。如果从当前位置开始执行到函数结束没有遇到yield,如果是next就会报StopIteration错误
"""
def func4():
    print('======1======')
    yield 100
    print('======2======')
    yield 200
    print('======3======')
    yield 300


gen2 = func4()
print(next(gen2))
for i in range(3):
    print('````````')

print(next(gen2))
print(next(gen2))
# print(next(gen2))   # StopIteration

gen3 = func4()
gen4 = func4()

print(next(gen3))   # 100
print(next(gen3))   # 200
print(next(gen4))   # 100


def func5():
    for i in range(5):
        yield i*2


# 重新调用函数则会重新开始
print(next(func5()))   # 0
print(next(func5()))   # 0
# 练习:写一个产生学号的生成器,能够产生指定学科001~999的学生学号
# python学生:python001~python999
# java学生:java001~java999


def student_id(str:str):
    for i in range(1, 1000):
        yield f'{str}{i:0>3}'
        # yield str+str(i).zfill(3)


py = student_id('python')
for i in range(1, 1000):
    print(next(py))

ja = student_id('java')
for i in range(1, 1000):
    print(next(ja))
# 练习:写一偶数个生成器,能够产生所有的正的偶数


def even():
    num = 2
    while True:
        yield num
        num += 2


even1 = even()
print(next(even1))
print(next(even1))

4.生成式 - 生成器的推导式

"""
将列表推导式[]变成(),创建的就是生成器的推导式即生成式
"""

四. 模块的使用

test模块

print('==========test开始==========')
A = 100


def func1():
    print('test1中的函数')


for X in range(10):
    pass
print('==========test结束==========')

test1模块

def sum1():
    print(sum(range(100)))


def main():
    sum1()


if __name__ == '__main__':
    main()

1.什么是模块

"""
python中一个py文件就是一个模块。
可以在一个模块中去使用另外一个模块的内容(全局变量),但需要提前导入模块
"""

2.导入模块

"""
1)import 模块名 - 导入能够使用指定模块中所有的全局变量;
               以'模块名.变量'形式去使用

2)from 模块名 import 变量名1,变量名2,...
a.导入模块,能使用模块中指定的全局变量;
b.直接使用对应的变量,不需要在前面加'模块名.'

3)import 模块名 as 新模块名
导入模块的时候对模块进行重命名,重命名后需要通过新模块名来使用被导入的模块

4)from 模块名 import 变量 as 新变量名,...
导入模块的时候对指定变量进行重命名

5)from 模块名 import *
导入模块中所有的全局变量
"""
# 导入方式一:import 模块名
import test
print(test.A)

test.func1()
print(test.X)
# 导入方式二:from 模块名 import 变量
from test import A, func1
print(A)
func1()
# 导入方式三:模块重命名
import test as ts
ts.func1()
print(ts.A)
print(ts.X)
# 本模块中的变量名与导入模块的变量名都可以使用
# 导入方式四:对变量重命名
from test import func1 as ts_func1


def func1():
    print('本模块中的func1')


func1()   # 本模块中的func1
ts_func1()   # test1中的函数

3.导入模块的原理

"""
不管是通过import还是from-import,在导入模块的时候,系统会自动将被导入的模块中所有的代码都执行一遍

注意:import导入模块的时候,自带查重功能(如果被导入的模块已经被导入过,不会重复导入)
"""
import test
import test
# *import 自带检测重复导入的功能*

4.阻止导入

"""
定义模块的时候,可以通过if __name__ == '__main__' 这个if语句来阻止模块
中的指定代码被其他模块在导入的执行。(在这个if语句中的代码不会被其他模块执行,
不在这个if语句中的代码就会被其他模块执行)

原理:
每个py文件中默认都有一个变量 __name__ 用来保存当前模块的模块名,
当直接执行某个py文件的时候这个文件中的__name__会自动变成"__main__"
"""

猜你喜欢

转载自blog.csdn.net/bbbbbya/article/details/109079126