【python基础学习】基础重点难点知识汇总

python中decorator装饰器

语法示例:

@decorator

什么是装饰器:

问题:
定义一个函数后
在运行时动态增加功能
又不想改动函数本身的代码

示例:

# 希望对下列函数调用增加log功能,打印出函数调用:
def f1(x):
    return x*2
def f2(x):
    return x*x
def f3(x):
    return x*x*x

方法1:直接修改原函数的定义

def f1(x):
    print(‘call f1‘)
    return x*2
def f2(x):
    print(‘call f2‘)
    return x*x
def f3(x):
    print(‘call f3‘)
    return x*x*x

有没有更简单的方法?

高阶函数
1. 可以接受函数作为参数
2. 可以返回函数
是否可以接受一个函数,对其进行包装,然后返回一个新函数?

方法2:通过高阶函数返回新函数(装饰器函数):

def f1(x):
    return x*2
def new_fn(f):
    def fn(x):
        print(‘call‘+f.__name__+‘()‘)
        return f(x)
    return fn

调用1:

g1 = new_fn(f1)
print( g1(5) )

调用2:

f1 = new_fn(f1)
print( f1(5) )

装饰器:

python内置@语法就是为了简化装饰器调用

@new_fn
def f1(x):
    return x*2

等同于:

def f1(x):
    return x*2
f1 = new_fn(f1)

装饰器的作用:

可以极大简化代码,避免每个函数编写重复性的代码
    打印日志:@log
    检测性能:@performance
    数据库事务:@transaction
    URL路由:@post(‘/register‘)

装饰器示例:

1. 如果自定义函数存在两个形参,上述装饰器函数内部固定写了一个形参,会出现错误怎么办:

@new_fn
def add(x,y):
    return x+y
# 这里会出现错误,所以需要更改 new_fn 函数如下:
def new_fn(f):
    def fn(*args, **kwargs):
        print(‘call‘+f.__name__+‘()‘)
        return f(*args, **kwargs)
    return fn

2. 请编写一个@performance,它可以打印出函数调用的时间。计算函数调用的时间可以记录调用前后的当前时间戳,然后计算两个时间戳的差。

import time
def performance(f):
    def fn(*args, **kw):
        t1 = time.time()
        r = f(*args, **kw)
        t2 = time.time()
        print ‘call %s() in %fs‘ % (f.__name__, (t2 - t1))
        return r
    return fn

@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)

3.上述装饰器函数只能接受一个函数参数,如果装饰器函数需要传入额外的参数怎么办?

@log(‘DEBUG‘)
def my_func():
    pass

把上面的定义翻译成高阶函数的调用,就是:

my_func = log(‘DEBUG‘)(my_func)

上面的语句看上去还是比较绕,再展开一下:

log_decorator = log(‘DEBUG‘)
my_func = log_decorator(my_func)

上面的语句又相当于:

log_decorator = log(‘DEBUG‘)
@log_decorator
def my_func():
    pass

所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数:

def log(prefix):
    def log_decorator(f):
        def wrapper(*args, **kw):
            print ‘[%s] %s()...‘ % (prefix, f.__name__)
            return f(*args, **kw)
        return wrapper
    return log_decorator

@log(‘DEBUG‘)
def test():
    pass
print test()

上述第二个例子:@performance只能打印秒,请给 @performace 增加一个参数,允许传入‘s‘或‘ms‘:

import time
import functools
def performance(unit):
    def perf_decorator(f):
        @functools.wraps(f)
        def wapper(*args, **kw):
            t1 = time.time()
            r = f(*args, **kw)
            t2 = time.time()
            t = (t2 - t1) * 1000 if unit==‘ms‘ else (t2 - t1)
            print ‘call %s() in %f %s‘ % (f.__name__, t,unit)
            return r
        return wapper
    return perf_decorator

@performance(‘ms‘)
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
print factorial.__name__

完善的装饰器写法:

原文地址:https://www.cnblogs.com/jiangxiaobo/p/11777294.html

时间: 2024-11-05 19:35:23

【python基础学习】基础重点难点知识汇总的相关文章

python零基础学习-基础知识1-python简介

编程语言分类方法1: 编译型: 如C,C++, 编写代码为源文件, 要编辑生成可执行文件才能执行 解释型: 如vbs, python无需编译, 使用解释器来执行, 可执行性更好; java使用了两者折中的方式, 编译生成的文件仍依靠解释器执行, 所以也属于解释型语 编程语言分类方法2: 动态类型语言: 无需指定变量类型, 如python, ruby, vbs等 静态类型语言: 编译时检查变量类型, 如c, c++, java, c# 编程语言分类方法3: 强类型定义语言: 变量类型无法转变, 如

python零基础学习-基础知识2-代码初见

注释及引号的使用 #我是一行注释 ''' 那么巧, 我也是一行注释 ''' print('''打印多行字符串-第一行 打印多行字符串-第二行 ''') print("我在尝试引号嵌套'我在尝试引号嵌套") print('那么巧, 我也在尝试引号嵌套"我也在尝试引号嵌套') 要求用户输入字符, 及字符串拼接 注意: 用户输入的都为字符串, 如需当做数字使用需要进行转换: int(age) #要求用户输入 name=input("what's your name?&qu

python零基础学习-基础知识3-模块,数据类型与计算

模块: 封装好的功能, 又叫库 标准库: 无需安装, 可直接导入, 如: sys, os.  注意: 导入库名不要与当前文件名相同 第三方库: 需下载安装, 才能使用 示例: import sys import os print(sys.path) #打印环境变量 print(sys.argv) #打印当前脚本的路径, pycharm中会打印绝对路径, cmd中会打印相对路径 #查看当前目录下所有文件 注意: 执行时可以输出到屏幕上, 但是不会存储下来 res=os.system("dir&qu

Python新手学习基础之初识python——与众不同1

Python是什么? 首先我们先简单介绍下python这门语言,Python是一种解释性的脚本语言,它不需要像C/C++那样先编译再执行,也不像JS那样可以在浏览器上直接执行.它为我们提供的基础代码库覆盖了网络.文件.GUI.数据库.文本等大量内容,你可以直接使用Python提供的功能而不用重新开始写.Python在服务端开发,GUI,数据挖掘等等各种领域都能很好的被运用......and so on想要多了解的朋友,可以自行度娘下吧. 知道了Python这门语言之后,我们也需要对它的语言特点进

Python新手学习基础之数据类型——字符串的切片截取

切片截取是Python中字符串常见的一些操作,我们会在这篇文章里详细介绍,切片截取的作用是获取子字符或子字符串. 实际上,我们要做的就是使用索引,用冒号分隔两个索引,形式为:变量[头下标:尾下标],冒号之前的数字表示开始的位置,冒号之后的数字表示结束的位置.这是一个左闭右开区间,也就是说这个字符串包含头下标,但是不包含尾下标. Python的数据有两种索引方式:最左边以0开始,依次增加:最右边的元素索引为-1,往左依次减少. Python的索引很灵活,可以根据具体情况来选择相应的索引方式. 字符

Python新手学习基础之数据类型——字符串类型

Python中字符串被定义为引号之间的字符集合,可以用 ' (一对单引号)或 " (一对双引号)括起来,字符串也可以被 """ (一对三个双引号)或者 ''' (一对三个单引号)括起来.使用索引运算符([ ])和切片运算符([ : ])可以得到子字符串.在Python中,字符串第一个字符的索引是0,而最后一个字符的索引是-1.索引和切片会在后面的文章中进行讲解. 让我们先来创建下字符串吧!例如: str1 = 'maya'   srt2 = 'coder' 字符串也

Python新手学习基础之条件语句——elif语句

elif语句 (相当于C语言的else if) 在Python中,当我们需要有更多的判断条件时,我们往往会使用另外一种语法表达,即使用elif: if 判断条件1: 执行语句1 elif 判断条件2: 执行语句2 elif 判断条件3: 执行语句3 ...... else: 执行语句n 现在我们有一个任务要完成,假设现在有一个分数,你他的等级如下: 90分及以上属于A:80分到89分属于B:70到79分属于C:60分到69分属于D: 0到59分属于E: 你需要用if/elif/else语句根据分

Python新手学习基础之运算符——成员运算与身份运算

成员运算符 Python里有成员运算符,可以判断一个元素是否在某一个序列中.比如可以判断一个字符是否属于这个字符串,可以判断某个对象是否在这个列表中等等. Python中的成员操作符的使用语法是: obj [not] in sequence 这个操作符返回值是True或者False. 看个代码实例吧: 身份运算符 Python支持对象本身的比较,比较的语法是: obj1 is [not] obj2 身份运算符是用来比较2个对象是否是同一个对象,而之前比较运算符中的 == 则是用来比较2个对象的值

Python新手学习基础之运算符——比较运算符

比较运算符 比较运算符可以使用比较两个值,所有的内建类型都支持比较运算.当用运算符比较两个值时,结果是一个逻辑值,不是True,就是False. 有一点要注意的是,不同的类型的比较方式不一样,数字类型会根据数字大小和正负进行比较,而字符串会根据字符串序列值进行比较等等. 在Python中有以下比较运算符: 现在我们就用比较运算符来完成一个小任务吧: 在x和y之间填入正确的比较运算符,来输出x和y的最大值,请主动思考哦~~~ 更多学习内容,就在码芽网http://www.mayacoder.com