python学习day4之路

装饰器(http://egon09.blog.51cto.com/9161406/1836763)

1、装饰器:本质是函数;

装饰器(装饰其他函数),就是为其他函数添加附加功能;

原则:1.不能修改被装饰函数的源代码;

2.不能修改被装饰的函数的调用方式;

装饰器对被装饰的函数完全透明的,没有修改被装饰函数的代码和调用方式。

实现装饰器知识储备:

1.函数即“变量”;

2.高阶函数;

3.嵌套函数

高阶函数+嵌套函数=》装饰器

匿名函数(lambda表达式)

>>> calc = lambda x:x*3

>>> calc(2)

6

高阶函数:

a.把一个函数名当做实参传递给另外一个函数;

>>> def bar():

print(“in the bar…..”)

>>> def foo(func):

print(func)

>>> foo(bar)

b.返回值中包含函数名;

>>> import time

>>> def foo():

time.sleep(3)

print(“in the foo…..”)

>>> def main(func):

print(func)

return func

>>> t = main(foo)



>>> t()

in the foo…..

装饰器:

在不修改源代码的情况下,统计程序运行的时间:

import time

def timmer(func):
    def warpper(*args,**kwargs):   #warpper(*args,**kwargs)万能参数,可以指定参数,也可以不指定参数
        start_time = time.time()     #计算时间
        func()
        stop_time = time.time()
        print("the func run time is %s" %(stop_time-start_time)) #计算函数的运行时间
    return warpper

@timmer    #等价于test1 = timmer(test1),因此函数的执行调用是在装饰器里面执行调用的
def test1():
    time.sleep(3)
    print("in the test1")

test1()
运行结果如下:

in the test1

the func run time is 3.001983404159546

装饰器带参数的情况:

import time

def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()     #计算时间
        func(*args,**kwargs)  #执行函数,装饰器参数情况
        stop_time = time.time()
        print("the func run time is %s" %(stop_time-start_time)) #计算函数的运行时间
    return warpper    #返回内层函数名

@timmer
def test1():
    time.sleep(3)
    print("in the test1")

@timmer    #test2 = timmer(test2)
def test2(name):
    print("in the test2 %s" %name)

test1()
test2("alex")
运行结果如下:

in the test1

the func run time is 3.0032410621643066

in the test2 alex

the func run time is 2.3603439331054688e-05

装饰器返回值情况:

import time
user,passwd = "alex","abc123"

def auth(func):
    def wrapper(*args,**kwargs):
        username = input("Username:").strip()
        password = input("Password:").strip()

        if user == username and passwd == password:
            print("33[32;1mUser has passed authentication.33[0m")
            return func(*args,**kwargs)   #实际上执行调用的函数   
            # res = func(*args,**kwargs)
            # return res   #函数返回值的情况,因为装饰器调用的时候是在装饰器调用的函数,因此返回值也在这个函数中
        else:
            exit("33[31;1mInvalid username or password.33[0m")
    return wrapper


def index():
    print("welcome to index page...")

@auth
def home():
    #用户自己页面
    print("welcome to home page...")
    return "form home..."

@auth
def bbs():
    print("welcome to bbs page")

index()
print(home())
bbs()

装饰器带参数的情况:

实现:1、本地验证;2、远程验证

import time
user,passwd = "alex","abc123"

def auth(auth_type):
    '''函数的多层嵌套,先执行外层函数'''
    print("auth_type",auth_type)
    def out_wrapper(func):
        def wrapper(*args,**kwargs):
            print("wrapper func args:",*args,**kwargs)
            if auth_type == "local":
                username = input("Username:").strip()
                password = input("Password:").strip()

                if user == username and passwd == password:
                    print("33[32;1mUser has passed authentication.33[0m")
                    func(*args,**kwargs)   #实际上执行调用的函数
                    # res = func(*args,**kwargs)
                    # return res   #函数返回值的情况,因为装饰器调用的时候是在装饰器调用的函数,因此返回值也在这个函数中
                else:
                    exit("33[31;1mInvalid username or password.33[0m")
            elif auth_type == "ldap":
                print("搞毛线lbap,傻逼....")
        return wrapper
    return out_wrapper


def index():
    print("welcome to index page...")

@auth(auth_type="local")
def home():
    #用户自己页面
    print("welcome to home page...")
    return "form home..."

@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")

index()
home()
bbs()   #函数没有,因为没有调用函数,函数的调用在装饰器里面,是装饰器调用了函数

迭代器和生成器

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

>>> l1 = (i for i in range(10))
>>> l1
<generator object at 0x7f6a9fbcaeb8>
>>> l1.__next__()
0
>>> l1.__next__()
1
生成器:只有在调用时才会生成相应的数据;

只有通过__next__()方法进行执行,这种能够记录程序运行的状态,yield用来生成迭代器函数。(只能往后调用,不能向前或者往后推移,只记住当前状态,因此银行的系统用来记录的时候可以使用yield函数)。

'''利用yield实现异步的效果,发送接收消息'''
import time

def consumer(name):
    '''消费者吃包子模型'''
    print("%s准备吃包子了......" %name)
    while True:
        '''循环,由于没有终止'''
        baozi = yield
        print("包子%s被%s吃了......" %(baozi,name))


def producer(boss):
    '''生产者生产包子模型,生产者要生产包子'''
    c1 = consumer("A")
    c2 = consumer("B")
    c1.__next__()
    c2.__next__()
    '''接下来,生产者要生产包子了,并传递给消费者'''
    for i in range(1,10):
        time.sleep(1)
        c1.send(i)
        c2.send(i)

producer("Alex")

运行如下:
A准备吃包子了......
B准备吃包子了......
包子1被A吃了......
包子1被B吃了......
包子2被A吃了......
包子2被B吃了......
包子3被A吃了......
包子3被B吃了......
包子4被A吃了......
包子4被B吃了......
包子5被A吃了......
包子5被B吃了......
包子6被A吃了......
包子6被B吃了......
包子7被A吃了......
包子7被B吃了......
包子8被A吃了......
包子8被B吃了......
包子9被A吃了......
包子9被B吃了.....

迭代器

我们已经知道,可以直接作用于 for
循环的数据类型有以下几种:

一类是集合数据类型,如 list
tuple
dict
set
str
等;

一类是 generator
,包括生成器和带 yield
的generator function。

这些可以直接作用于 for
循环的对象统称为可迭代对象: Iterable

可以使用 isinstance()
判断一个对象是否是 Iterable
对象

>>>
from
collections
import
Iterable

>>>
isinstance
([], Iterable)

True

>>>
isinstance
({}, Iterable)

True

>>>
isinstance
(
'abc'
, Iterable)

True

>>>
isinstance
((x
for
x
in
range
(
10
)), Iterable)

True

>>>
isinstance
(
100
, Iterable)

False

Python_博客园稿源:Python_博客园 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 综合编程 » python学习day4之路

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录