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

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.装饰器带参数

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.多层装饰器

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道题

# 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
# 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
# 数据类型的强制转换 : 占用内存
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不能接受外部的值
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.计算移动平均值

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

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

#这个装饰器的目的就是提前激活程序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

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的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和: 

# 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
#[每一个元素或者是和元素相关的操作 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.提高代码可读性

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.刷题

# 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.生成器表达式面试题

# 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()——获取执行本方法所在命名空间内的局部变量的字典

# 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.进度条

#进度条子
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

 

 
posted on 2018-06-26 19:21  快叫洪哥  阅读(220)  评论(0编辑  收藏  举报