python学习笔记-Day05-第一部分(再谈装饰器)(递归)

今天又花了多半天来学习装X利器---装饰器,

来详细的讲讲装饰器的用法

还是要说一下,学装饰器之前要先搞清楚什么是函数。装饰器就是对函数进行一个包装,打个比喻来说就是:

假设有一个箱子A,在箱子A的外面又套了一个大箱子,外面的大箱子还起名叫A,以后在找里面的小箱子A的时候,就先去找外面的大箱子A,打开外面的大箱子A之后 在打开内部的小箱子A,这个就是装饰器。

  1. 装饰器也是一个函数,至少两层
def outter(func):               #定义函数 outter,参数为一个函数的函数名,这里为func,
    def inner():                    #定义函数inner
        print "before"
        tmp = func()              #执行函数func(), 这里的func为outter的参数
        print "after"
        return tmp
    return inner                  #  返回函数名inner

@outter                              # 给下面的函数加装饰器,这里是一个语法糖
def foo():                            # 定义函数foo
    print "foo"

foo()                                    #指定函数foo(),这里的  foo() 函数为经过装饰器装饰的函数

输出:

before
foo
after

2. 执行上面代码的时候,被装饰的函数foo()的函数名foo作为参数,即outter(foo); outter函数的返回值,重新赋值给被装饰的函数的函数名

3.装饰器可以装饰有N(N>=0)个参数的函数,对于有不同个数参数的函数来说,装饰器使用动态参数来处理传参的问题,我们修改上面的例子,修改后就解决了传参的问题:

4.  函数的返回值,如果函数有返回值,我们就要考虑函数的返回值如何传递回来,直接将函数的返回结果return就可以了:

def outter(func):
    def inner(*args,**kwargs):     #设置参数
        print "before"
        tmp = func(*args,**kwargs)  #设置参数,这里的参数和inner的参数一样
        print "after" 
        return tmp        # 变量tmp的值为func(*args,**kwargs)的执行结果,返回装饰后函数的返回值
    return inner
@outter
def foo(arg,*args):
    print arg,"---",args

foo(1,2,3,4)

5.多装饰器

一个函数可以被多个函数同时装饰,函数被多个装饰器装饰的时候,效果类似于俄罗斯套娃。

def w1(fun):
    def inner():
        print "w1,before"
        fun()
        print "w1,after"
    return inner
def w2(fun):
    def inner():
        print "w2,before"
        fun()
        print "w2,after"
    return  inner
@w2
@w1
def foo():
    print "foo"
foo()

执行结果

w2,before
w1,before
foo
w1,after
w2,after

6. 带参数的装饰器(至少三层)

就是给函数加装饰器的时候,装饰器还带有参数,代码如下:

def Filter(before_func,after_func):
    pass
@Filter(Before, After)
def Index(request,kargs):
    pass

现在上完整代码,然后解释:

def Before(request,kargs):  #1 加载Before函数到内存
                            #14 执行函数 Before
                            
    print ‘before‘     #15 执行print语句
    
def After(request,kargs): #2 加载After到内存
                            #21 执行After函数
                            
    print ‘after‘    #22 执行print语句
    
def Filter(before_func,after_func): #3 加载函数Filter到内存
                                    #5 执行装饰器Filter
                                    
    def outer(main_func):           #6 加载函数outer到内存
                                    #8 执行函数outer
                                    
        def wrapper(request,kargs):  #9  加载函数wrapper
                                     #12 执行函数wrapper
                                     
            before_result = before_func(request,kargs)  #13 给before_result赋值
            
            if(before_result != None):  # 16 执行if语句,这里判断为假
                return before_result
                
            main_result = main_func(request,kargs) #17 给变量main_result赋值
            
            if(main_result != None):        #19 执行if语句,这里判断为假
            
                return main_result
            after_result = after_func(request,kargs) #20 给after_result赋值
            
            if(after_result != None):  #23 执行if语句, 这里判断为假
                return after_result
                
        return wrapper  #10 返回函数outer的返回值,warapper
        
    return outer  #7 返回Filter函数的返回值,即函数名outer
    
@Filter(Before, After)  #4 发现装饰器Filter,
                        #17 执行Filter(Before, After)
                        
def Index(request,kargs):

    print ‘index‘     #18 执行print语句
    
Index("quest0","kwargs0")  #11 执行函数 Index

###############################################################

递归

递归算法是一种  直接或间接的调用自身的一种算法。

打个比喻来说就向下面这样

从前有座山,山上有座庙,庙里有个老和尚,老和尚对小和尚说:从前有座山,山上有座庙,庙里有个老和尚,老和尚对小和尚说:从前有座山,山上有座庙,庙里有个老和尚,老和尚对小和尚说。。。。。。。。

递归算法可以有效的解决一大类问题,比如经典的  汉诺塔(又称河内塔)问题,

递归算法的特点是

1.  在函数或者过程里调用自身

2.  必须有一个明确的条件,可以让递归结束

3.  算法简洁,但是效率低

4.  容易造成栈溢出(因为在执行过程中,每一层的返回点、局部变量等都要开辟栈来存储)

以实现斐波那契数列为例:

def fib(a1,a2):
    # print a1,a2,
    a3=a1+a2
    if a3>100:    #这里加入了结束条件,如果没有这个条件,会形成死循环
        return a3
    # print a3,
    return fib(a2,a3)
    # fib(a2,a3)
print fib(0,1)

递归是可以和while互相转换的。

上面的代码用while循环来实现的的代码是:

a1,a2 = 0,1
while a1<200:
    print a1
    a2=a1+a2
    a1=a2-a1

http://timesnotes.blog.51cto.com/1079212/1716574

http://www.timesnotes.com/?p=114

时间: 2024-10-26 00:05:34

python学习笔记-Day05-第一部分(再谈装饰器)(递归)的相关文章

C++ Primer 学习笔记_73_面向对象编程 --再谈文本查询示例

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

C++ Primer 学习笔记_74_面向对象编程 --再谈文本查询示例[续/习题]

面向对象编程 --再谈文本查询示例[续/习题] //P522 习题15.41 //1 in TextQuery.h #ifndef TEXTQUERY_H_INCLUDED #define TEXTQUERY_H_INCLUDED #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <set> #include <map&g

【Python学习笔记之二】浅谈Python的yield用法

在上篇[Python学习笔记之一]Python关键字及其总结中我提到了yield,本篇文章我将会重点说明yield的用法 在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor). 一.迭代器(iterator) 在Python中,for循环可以用于Python中的任何类型,包括列表.元祖等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器 迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前

C++ Primer 学习笔记_73_面向对象编程 -再谈文本查询示范

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

C++ Primer 学习笔记_74_面向对象编程 -再谈文本查询示范[续/习题]

面向对象编程 --再谈文本查询示例[续/习题] //P522 习题15.41 //1 in TextQuery.h #ifndef TEXTQUERY_H_INCLUDED #define TEXTQUERY_H_INCLUDED #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <set> #include <map&g

python day4笔记 常用内置函数与装饰器

1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any             判断迭代器中的数据是否有一个为真,有返回真,可迭代数据为空或者没有真,返回假 bin             转换整数为二进制字符串 hex            转换整数为十六进制字符串 oct             转换整数为八进制字符串 bool           转换数据为布尔值

python学习之类和实例的属性;装饰器@property

无论是类还是实例,一切皆是对象. Python是强动态语言,和java在这点上有所不同. class Ab(): a = 666 # 定义类对象Ab,自带属性a,值为666 # 使用Ab.__dict__可以查看类Ab的属性 us1 = Ab() us2 = Ab() # 定义两个实例对象us1.us2,这两个实例自身并不具备任何属性 # 只有在__init__中定义了self.arg=xxx的情况下,实例默认会具备arg属性 动态语言中,属性自带操作方法:获取(读).设置(写):还可以定义删除

流程python学习笔记:第一章

这一章中作者简要的介绍了python数据模型,主要是python的一些特殊方法.比如__len__, __getitem__. 并用一个纸牌的程序来讲解了这些方法 首先介绍下Tuple和nametuple的区别: Nametuple是类似于元组的数据类型.除了能够用索引来访问数据,还支持用方便的属性名来访问数据. 传统的元组访问如下.对每个元素的访问都必须通过索引来找到.这种找法很不直观 tup1=('abc','def','ghi') print tup1[1] 使用nametuple来构造:

python学习笔记(第一周):变量

在python中申明一个变量,不需要申明变量的类型,如下: name = "Eraser Li" 打印变量,代码如下: print("My name is",name) 控制台输出结果: My name is Eraser Li 变量赋值给变量: name2 = name print("My name is",name2) 控制台输出结果: My name is Eraser Li 现在给name重新赋值: name = "Eraser