欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

我的自学Python之路(第二阶段Day8)

程序员文章站 2022-06-24 12:58:03
1.装饰器和函数的一些用法 from functools import wraps def wrapper(func): @wraps(func) def inner(): func() return inner @wrapper def func1(): '''jisfhsdkfkd''' pri ......

1.装饰器和函数的一些用法

我的自学Python之路(第二阶段Day8)
from functools import wraps
def wrapper(func):
    @wraps(func)
    def inner():
        func()
    return inner
@wrapper
def func1():
    '''jisfhsdkfkd'''
    print('ddf')
print(func1.__name__)
func1()
print(func1.__doc__)

# def index():
#     '''这是一个主页信息'''
#     print('from index')
#
# print(index.__doc__)    #查看函数注释的方法
# print(index.__name__)   #查看函数名的方法
View Code

2.装饰器带参数

我的自学Python之路(第二阶段Day8)
FLAG = True
def out(flag):
    def wrapper(func):

        def inner():
            if flag:
                print(123)
                func()
            else:
                func()
        return inner
    return wrapper
@out(FLAG)
def func1():
    '''jisfhsdkfkd'''
    print('ddf')
func1()
View Code

3.多层装饰器

我的自学Python之路(第二阶段Day8)
def wrapper1(func):
    def inner1():
        print('wrapper1 ,before func')
        ret = func()
        print('wrapper1 ,after func')
        return ret
    return inner1

def wrapper2(func):
    def inner2():
        print('wrapper2 ,before func')
        ret = func()
        print('wrapper2 ,after func')
        return ret
    return inner2

def wrapper3(func):
    def inner3():
        print('wrapper3 ,before func')
        ret = func()
        print('wrapper3 ,after func')
        return ret
    return inner3

@wrapper3
@wrapper2
@wrapper1
def f():
    print('in f')
    return '哈哈哈'

print(f())

执行结果
wrapper3 ,before func
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
wrapper3 ,after func
哈哈哈
View Code

 4.刷2道题

我的自学Python之路(第二阶段Day8)
# 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 要求登录成功一次,后续的函数都无需再输入用户名和密码
# FLAG = False
# def login(func):
#     def inner(*args,**kwargs):
#         global FLAG
#         '''登录程序'''
#         if FLAG:
#             ret = func(*args, **kwargs)
#             return ret
#         else:
#             username = input('username:')
#             password = input('password:')
#             if username == 'boss_gold' and password == '22222':
#                 FLAG = True
#                 ret = func(*args,**kwargs)
#                 return ret
#             else:
#                 print('登录失败')
#     return inner
# @login
# def shop_add():
#     print('增加一件物品')
# @login
# def shop_del():
#     print('删除一件物品')
# shop_add()
# shop_del()


# 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
def log(func):
    def inner(*args,**kwargs):
        with open('log','a',encoding = 'utf-8') as f:
            f.write(func.__name__ + '\n')
        ret = func(*args,**kwargs)
        return ret
    return inner
@log
def shop_add():
    print('增加一件物品')
@log
def shop_del():
    print('删除一件物品')
shop_add()
shop_del()
View Code
我的自学Python之路(第二阶段Day8)
# 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
# 2.为题目1编写装饰器,实现缓存网页内容的功能:
# 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
import os
from urllib.request import urlopen
def cache(func):
    def inner(*args,**kwargs):
        if os.path.getsize('web_cache'):
            with open('web_cache','rb') as f:
                return f.read()
        ret = func(*args,**kwargs)
        with open('web_cache','wb') as f:
            f.write(b'***'+ret)
        return ret
    return inner

@cache
def get(url):
    code = urlopen(url).read()
    return code

ret = get('http://www.baidu.com')
print(ret)

ret = get('http://www.baidu.com')
print(ret)
View Code

5.从生成器中取值的几个方法

    # next
# for
# 数据类型的强制转换 : 占用内存
我的自学Python之路(第二阶段Day8)
def generator():
    for i in range(20):
        yield '哇哈哈%s'%i

g = generator()  #调用生成器函数得到一个生成器
print(list(g))# 数据类型的强制转换 : 占用内存
# ret = g.__next__()     #每一次执行g.__next__就是从生成器中取值,预示着生成器函数中的代码继续执行
# print(ret)
# num = 0
# for i in g:
#     num += 1
#     if num > 5:
#         break
#     print(i)
View Code

 6 .#生成器函数进阶

#send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
我的自学Python之路(第二阶段Day8)
def generator():
    print(123)
    content = yield 1
    print(content)
    print(456)
    yield 2
    print(789)

g = generator()
print(g.__next__())
print(g.send('hello'))
print(g.send('hello'))
View Code

7.计算移动平均值

我的自学Python之路(第二阶段Day8)
def average():
   sum = 0
   count = 0
   avg = 0
   while 1:
       num = yield avg
       sum = sum + num
       count += 1
       avg = sum/count

avg_g = average()
avg_g.__next__()
avg1 = avg_g.send(10)
# avg1 = avg_g.send(50)


print(avg1)
View Code

计算移动平均值---预激协程的装饰器

我的自学Python之路(第二阶段Day8)
#这个装饰器的目的就是提前激活程序g.__next__()
#方便客户计算的时候不用再执行g.__next__()
# def init(func):   #装饰器
#     def inner(*args,**kwargs):
#         g = func(*args,**kwargs)    #g = average()
#         g.__next__()
#         return g
#     return inner
#
# @init
# def average():
#     sum = 0
#     count = 0
#     avg = 0
#     while True:
#         num = yield avg
#         sum += num    # 10
#         count += 1    # 1
#         avg = sum/count
#
# avg_g = average()   #===> inner
# ret = avg_g.send(10)
# print(ret)
# ret = avg_g.send(20)
# print(ret)
View Code

8.yield from

我的自学Python之路(第二阶段Day8)
def generator():
    a = 'adfgg'
    b = 'dskdl'
    for i in a:#两句话相当于==》yield from a
        yield i#两句话相当于==》yield from a
    for i in b:
        yield i
g = generator()
for i in g:
    print(i)
View Code

9.列表推导式和生成器表达式

总结:

1.把列表解析的[]换成()得到的就是生成器表达式

2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和: 

我的自学Python之路(第二阶段Day8)
# egg_list = ['鸡蛋%s' %i for i in range(10)]#列表解析
# print(egg_list)
# egg_tur = ('鸡蛋%s' %i for i in range(10))#生成器表达式
# print(egg_tur)
# print(egg_tur.__next__())
# print(next(egg_tur)) #next本质就是调用__next__
# print(egg_tur.__next__())


t = sum(x ** 2 for x in range(4))
print(t)
s = sum([x ** 2 for x in range(4)])
print(s)
m = sum((0,1,4,9))
print(m)
print(sum((1,2)))
View Code
我的自学Python之路(第二阶段Day8)
#[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型]    #遍历之后挨个处理
#[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件]   #筛选功能

# #30以内所有能被3整除的数
# print([i for i in range(30) if i%3 == 0])
# print((i for i in range(30) if i%3 == 0))
# # 例三:找到嵌套列表中名字含有两个‘e’的所有名字
# names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
#          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
# ret = [name for lst in names for name in lst if name.count('e') ==2]
# # ret = (name for lst in names for name in lst if name.count('e') ==2)
# print(ret)
#

#字典推导式


# 例一:将一个字典的key和value对调
# dic = {'a':10,'b':20}
# dic_reverse = {dic[k]:k for k in dic}
# print(dic_reverse)
#

# 例二:合并大小写对应的value值,将k统一成小写
# d = {'s':10}
# print(d.get('b',0))
# print(d.get('s'))

# mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
# s = {k.lower():mcase.get(k.lower(),0) + mcase.get(k.upper(),0) for k in mcase}
# print(s)

#集合推导式,自带结果去重功能

# s = {x**2 for x in [1,2,-1]}
# print(s)
# squared = {x**2 for x in [1, -1, 2]}
# print(squared)


#各种推导式 : 生成器 列表 字典 集合
    #遍历操作
    #筛选操作
View Code

10.生成器Generator:

  本质:迭代器,所以拥有__iter__方法和__next__方法

  特点:惰性运算,开发者自定义

使用生成器的优点:

1.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

 2.提高代码可读性

我的自学Python之路(第二阶段Day8)
print(sum([i for i in range(100)]))#内存占用大,机器容易卡死
print(sum(i for i in range(100000)))#几乎不占内存
print(i for i in range(100))#几乎不占内存
View Code

 11.刷题

我的自学Python之路(第二阶段Day8)
# 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕

# def func(filename,s):
#     with open(filename,encoding = 'utf-8') as f1:
#         for i in f1:
#             if s in i:
#                 yield i
#
# g = func('ss','生成器')
# for i in g:
#     print(i.strip())

# def check_file(filename,aim):
#     with open(filename,encoding='utf-8') as f:   #句柄 : handler,文件操作符,文件句柄
#         for i in f:
#             if aim in i:
#                 yield i
#
# g = check_file('1.复习.py','生成器')
# for i in g:
#     print(i.strip())

# 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
# def check_file(filename):
#     with open(filename,encoding='utf-8') as f:   #句柄 : handler,文件操作符,文件句柄
#         for i in f:
#             yield '***'+i
#
# for i in check_file('1.复习.py'):
#     print(i.strip())
def func(filename):
    with open(filename,encoding = 'utf-8') as f1:
        for i in f1:
            yield '***'+i


g = func('ss')
for i in g:
    print(i.strip())
View Code

 12.生成器表达式面试题

我的自学Python之路(第二阶段Day8)
# def demo():
#     for i in range(4):
#         yield i
#
# g=demo()
#
# g1=(i for i in g)
# g2=(i for i in g1)
#
# print(list(g))
# print(list(g1))
# print(list(g2))

def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g=test()
# for n in [1,10,5]:
#     g=(add(n,i) for i in g)
n = 1
g=(add(n,i) for i in test())
n = 10
g=(add(n,i) for i in (add(n,i) for i in test()))
n = 5
g=(15,16,17,18)


print(list(g))
View Code

13.内置函数

作用域相关

基于字典的形式获取局部变量和全局变量

globals()——获取全局变量的字典

locals()——获取执行本方法所在命名空间内的局部变量的字典

我的自学Python之路(第二阶段Day8)
# print()
# input()
# len()
# type()
# open()
# tuple()
# list()
# int()
# bool()
# set()
# dir()
# id()
# str()


# print(locals())  #返回本地作用域中的所有名字
# print(globals()) #返回全局作用域中的所有名字
# global 变量
# nonlocal 变量

#迭代器.__next__()
# next(迭代器)
# 迭代器 = iter(可迭代的)
# 迭代器 = 可迭代的.__iter__()

# range(10)
# range(1,11)
# print('__next__' in dir(range(1,11,2)))

# dir 查看一个变量拥有的方法
# print(dir([]))
# print(dir(1))

# help
# help(str)

# 变量
# print(callable(print))
# a = 1
# print(callable(a))
# print(callable(globals))
# def func():pass
# print(callable(func))

import time
# t = __import__('time')
# print(t.time())

# 某个方法属于某个数据类型的变量,就用.调用
# 如果某个方法不依赖于任何数据类型,就直接调用  —— 内置函数 和 自定义函数

# f = open('1.复习.py')
# print(f.writable())
# print(f.readable())

#id
#hash - 对于相同可hash数据的hash值在一次程序的执行过程中总是不变的
#     - 字典的寻址方式
# print(hash(12345))
# print(hash('hsgda不想你走,nklgkds'))
# print(hash(('1','aaa')))
# print(hash([]))

# ret = input('提示 : ')
# print(ret)

# print('我们的祖国是花园',end='')  #指定输出的结束符
# print('我们的祖国是花园',end='')
# print(1,2,3,4,5,sep='|') #指定输出多个值之间的分隔符
# f = open('file','w')
# print('aaaa',file=f)
# f.close()

# import time
# for i in range(0,101,2):
#      time.sleep(0.1)
#      char_num = i//2
#      per_str = '\r%s%% : %s\n' % (i, '*' * char_num) \
#          if i == 100 else '\r%s%% : %s' % (i,'*'*char_num)
#      print(per_str,end='', flush=True)
View Code

14.进度条

我的自学Python之路(第二阶段Day8)
#进度条子
import time
for i in range(0,101,2):
     time.sleep(0.1)
     char_num = i//2
     per_str = '\r%s%% : %s\n' % (i, '*' * char_num) \
         if i == 100 else '\r%s%% : %s' % (i,'*'*char_num)
     print(per_str,end='', flush=True)
View Code