一、装饰器

装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面每个函数都加一个功能,用来统计每个函数的运行时间是多少,找出来运行比较慢的函数,来优化代码,就需要添加一个新的功能,来统计程序的运行时间,那这样的话,就得修改每个函数了,需要改代码,但是代码特别多,改完了公司倒闭了,这时候装饰器就能排上用场了,它可以不改变原有的函数,原来的函数和原来一模一样,什么都不需要改变,只需要在函数外部加上调用哪个装饰器就可以了。so,装饰器的作用就是不改变原来函数的调用方式,不改变原来函数的代码,给它增加了一个新功能。但是不改变函数,给它增加新功能,那是不可能的,装饰器只不过是偷偷改变了原来的函数而已,而原来的函数不知不觉。

使用装饰器需要了解的知识:

1、函数即变量,这个是什么意思呢,在python里面函数就是一个变量,函数名就是一个变量,这个函数名里面存的是这个函数的内存地址,它把函数体放到内存里,在调用的时候从函数名里面的这个内存地址找到函数体然后运行这个函数。前面的博客说函数的时候,说过函数名后面加上小括号就是调用这个函数,如果只写这个函数名的话,打印一下就是这个函数的内存地址。

def test():
print('nihao')
prinit(test)#打印函数的内存地址
test()#调用函数

运行结果:

<function test at 0x100699950>
nihao

2、高阶函数,高阶函数在上篇博客里面写了,如果函数的入参是一个函数的话,那么这个函数就是一个高阶函数。

3、函数嵌套,函数嵌套,函数嵌套就是在函数里面再定义一个函数,这就是函数嵌套,而不是说在函数里面再调用一个函数。

 def test():
def test1():
print('test1')
print('test')

了解了上面的这些知识之后,就可以使用装饰器了,下面我写一个简单的装饰器,用来统计函数的运行时间,然后将被统计的函数作为参数传递

import time
def bar():
time.sleep(3)
print('in the bar')
def test1(func):
start_time=time.time()
func()
stop_time = time.time()
print('the func run time is %s' % (stop_time - start_time))
test1(bar)

运行结果:

in the bar
the func run time is 3.000171661376953

但是这样的话,我们每次都要将一个函数作为参数传递给test1函数。改变了函数调用方式,之前执行业务逻辑时,执行运行bar(),但是现在不得不改成test1(bar)。此时就要用到装饰器。我们就来想想办法不修改调用的代码;如果不修改调用代码,也就意味着调用bar()需要产生调用test1(bar)的效果。我们可以想到将test1赋值给bar,但是test1似乎带有一个参数……想办法把参数统一吧!如果test1(bar)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数的话……就很好办了,将test1(bar)的返回值赋值给bar,然后,调用bar()的代码完全不用修改!

        import time
def timmer(func):
def deco():
start_time=time.time()
func()
stop_time=time.time()
print('the func run time is %s'%(stop_time-start_time))
return deco
def bar():
time.sleep(3)
print('in the bar')
bar=timmer(bar)
bar()

运行结果:

 in the bar
the func run time is 3.000171661376953

函数timmer就是装饰器,它把执行真正业务方法的func包裹在函数里面,看起来像bar被timmer装饰了。如果我们要定义函数时使用装饰器,避免使用赋值语句bar=timmer(bar),要用到装饰器的语法糖@,语法糖的意思就是一种语法的简写,它使代码看起来简洁,上面的bar=timmer(bar)和@timmter bar()是一样的。这样写的话,看起来也比较高大上一些。

        import time
def timmer(func):
def deco():
start_time=time.time()
func()
stop_time=time.time()
print('the func run time is %s'%(stop_time-start_time))
return deco
@timmer
def bar():
time.sleep(3)
print('in the bar')
bar()

运行结果:

in the bar
the func run time is 3.000171661376953

这样,我们就提高了程序的可重复利用性,当其他函数需要调用装饰器时,可以直接调用。装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。

如果要装饰的函数带有参数时,因为你也不知道到底被装饰的函数会传什么参数,所以可以使用可变参数和关键字参数来接收所有的参数,这两种参数也在上一篇博客中写过了。代码如下:

        import time
def timmer(func):
def deco(*arg,**kwarg):
start_time=time.time()
func(*arg,**kwarg)
stop_time=time.time()
print('the func run time is %s'%(stop_time-start_time))
return deco
@timmer
def test1():
time.sleep(1)
print('in the test1')
@timmer
def test2(name,age) :
time.sleep(2)
print('in the test2:',name,age)
test1()
test2('niuniu,18)

运行结果:

in the test1
the func run time is 1.0000572204589844
in the test2: niuniu 18
the func run time is 2.0001144409179688

下面再用装饰器,写一个实例,判断用户是否登陆,逻辑是这样,运行程序,打印菜单,如果是选择后台管理和添加商品,就判断用户是否登录,如果没有登录的话,让用户登录,如果是查看商品就不需要登录。

    import os
def login():
'''
登录函数,登录成功的话,写如user这个文件
:return:
'''
print('login')
username = input('请输入账号')
password = input('请输入密码')
if username =='admin' and password=='':
print('登录成功!')
with open('user','a+') as fw:
fw.write(username)
else:
print('账号密码错误!')
#是否登录校验装饰器
def auth(func):
def check(*args,**kwargs):
if os.path.exists('user'):#判断用户文件是否存在
func(*args,**kwargs)#存在的话,调用原来的函数
else:
print('你未登陆!')#不存在的话,调用登录函数
login()
return check
@auth
def admin():
print('welcome!')
def show():
print('show!')
@auth
def add():
print('add product!')
def menu():#打印菜单函数
msg= '''
1 : 后台管理
2 : 查看商品
3 : 添加商品
'''
print(msg)
m = {
"":admin,
"":show,
"":add
}
choice = input('请输入你的选择:').strip()
if choice in m:
m[choice]()#调用对应的函数
else:
print('输入错误!')
menu()
if __name__ == '__main__':
menu()

二、生成器

生成器是什么东西呢,可以理解为,生成器也是一个迭代的对象,和list似的,里面存数据,和list不同的是,list在定义的时候数据就已经在内存里面了,而生成器是,你用到这个里面的数据的时候它才会生成,这样就比较省内存,因为是需要这个值的时候,才会在内存里面产生。生成器是按照某种规则生成的一个列表,用到这个列表的中的数据时,才会在内存里生成,但是由于生成器是根据某种规则产生的,必须得知道前一个值是多少,才能知道后面的那个值是多少,所以不能像list那样,直接用索引去取值。

1、 列表生成式,在第二篇博客里面我写了三元运算符,和那个有点像,如果要生成列表[1x1, 2x2, 3x3, ..., 10x10]怎么做?除了循环还可以用一行语句代替循环生成

list=[x*x for x in range(1,11)]
print(list)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]#运行结果

这种写法就是Python的列表生成式,写列表生成式时,把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把list创建出来。

2、生成器:要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator。

g=(x*x for x in range(1,11))
print(g)
<generator object <genexpr> at 0x1036ff258>#运行结果

创建list和generator的区别仅在于最外层的[]和()。list的元素我们可以一个个打印出,如果要打印generator中的元素需要借助next方法

g=(x*x for x in range(1,11))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

运行结果:

        1
4
9
16

用函数生成generator:generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。例如,斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):
n,a,b=0,0,1
while n<max:
print(b)
a,b=b,a+b
n=n+1
return 'done'
f=fib(6)

运行结果:

    1
1
2
3
5
8

上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n=n+1
return 'done'
x = fib(6)
print(x)
print(x.__next__())
print(x.__next__())
print(x.__next__())
print(x.__next__())

三、内置函数

        print(all([1,2,3,4]))#判断可迭代的对象里面的值是否都为真
print(any([0,1,2,3,4]))#判断可迭代的对象里面的值是否有一个为真
print(bin(10))#十进制转二进制
print(bool('s'))#把一个对象转换成布尔类型
print(bytearray('abcde',encoding='utf-8'))#把字符串变成一个可修改的bytes
print(callable('aa'))#判断传入的对象是否可调用
print(chr(10))#打印数字对应的ascii
print(ord('b'))#打印字符串对应的ascii码
print(dict(a=1,b=2))#转换字典
print(dir(1))#打印传入对象的可调用方法
print(eval('[]'))#执行python代码,只能执行简单的,定义数据类型和运算
print(exec('def a():pass'))#执行python代码
print(filter(lambda x:x>5,[12,3,12,2,1,2,35]))#把后面的迭代对象根据前面的方法筛选
print(map(lambda x:x>5,[1,2,3,4,5,6]))
print(frozenset({1,2,3,3}))#定义一个不可修改的集合
print(globals())#返回程序内所有的变量,返回的是一个字典
print(locals())#返回局部变量
print(hash('aaa'))#把一个字符串哈希成一个数字
print(hex(111))#数字转成16进制
print(max(111,12))#取最大值
print(oct(111))#把数字转换成8进制
print(round(11.11,2))#取几位小数
print(sorted([2,31,34,6,1,23,4]))#排序
dic={1:2,3:4,5:6,7:8}
print(sorted(dic.items()))#按照字典的key排序
print(sorted(dic.items(),key=lambda x:x[1]))#按照字典的value排序
__import__('decorator')#导入一个模块

四、匿名函数

如果这个函数只执行一次的话,那就可以定义一个匿名函数,匿名函数只能处理比较简单的处理逻辑,只能写简单的表达式,不能写循环 判断,比如三元运算符。

匿名函数定义使用lambda关键字,比如说要定义一个函数,它的功能是返回两个数相加和,就可以使用lambda,代码如下:

s = lambda x,y:x+y#冒号号前面的x,y是入参,冒号后面的是返回值
print(s(1,9))#因为函数即变量,如果没有定一个变量把lambda存起来的话,它就不在内存里,没法执行,所有把它放到s这个变量里面

五、json处理

    import json
dic = {"name":"niuniu","age":18}
print(json.dumps(dic))#把字典转成json串
fj = open('a.json','w')
print(json.dump(dic,fj))#把字典转换成的json串写到一个文件里面
s_json = '{"name":"niuniu","age":20,"status":true}'
print(json.loads(s_json))#把json串转换成字典
fr = open('b.json','r')
print(json.load(fr))#从文件中读取json数据,然后转成字典

python学习笔记(五):装饰器、生成器、内置函数、json的更多相关文章

  1. python学习笔记:第14天 内置函数补充和递归

    一.匿名函数 匿名函数主要是为了解决一些简单需求而设计的一种函数,匿名函数的语法为: lambda 形参: 返回值 先来看一个例子: # 计算n的n次方 In[2]: lst = lambda n: ...

  2. python学习笔记(十六)内置函数zip、map、filter的使用

    1.zip,就是把两个或者多个list,合并到一起,如果想同时循环2个list的时候,就使用zip.示例如下: l1 = ['a','b','c','e','f','g'] l2 = [,,] l3= ...

  3. python学习笔记:第13天 内置函数(一)

    详细文件查看点击这里:详细地址

  4. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  5. python笔记5:装饰器、内置函数、json

    装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象. 先看简单例子: def run(): time.sleep(1 ...

  6. Python学习笔记之装饰器原理

    def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...

  7. 万恶之源 - Python装饰器及内置函数

    装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...

  8. Python装饰器及内置函数

    装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...

  9. 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

    一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...

随机推荐

  1. 敏捷BI与数据驱动机制

    大数据这件事,整体上还是说的多一些,做的稍微少一点.大数据可以是荒凉高原上波澜壮阔的机房,也可以润物细无声般融入到日常生活和工作.换句话说,大数据应该是一种文化. 在个人层面,很多人对数字和计算并不敏 ...

  2. .Net快速获取网络文本文件最后一段文字-小应用

    场景 现在公司的测试环境一些文本日志不让接触,提供一个网络http服务器让人直接访问,这文件大时,一般10MB一个文件,不在同一局域网,网速限制200K,要等很久,访问很慢. .Net代码请求文本文件 ...

  3. BeautifulSoup的安装和使用

    Python用做数据处理还是相当不错的,如果你想要做爬虫,python是很好的选择,它有很多已经写好的类包,只要调用,即可完成很多复杂的功能,此文中所有的功能都是基于BeautifulSoup这个包. ...

  4. $.ajax 的速度要快于 angular 里 $http (个别情况)

    $.ajax: $http:

  5. IOS开发 警告 All interface orientations must be supported unless the app requires full screen.

    在IOS开发中遇到警告  All interface orientations must be supported unless the app requires full screen. 只要勾上R ...

  6. vuex(一)mutations

    前言:vuex的使用,想必大家也都知道,类似于状态库的东西,存储某种状态,共互不相干的两个组件之间数据的共享传递等.我会分开给大家讲解vuex的使用,了解并掌握vuex的核心(state,mutati ...

  7. 【剑指offer】左旋转字符串,C+实现

    原创博文,转载请注明出处! 本题牛客网地址 本题代码的github地址 本系列文章的索引地址 # 题目 # 思路 先局部翻转,后整体翻转.举例:abcdefg先局部翻转为bagfedc,后整体翻转为c ...

  8. 《DSP using MATLAB》示例Example 6.9

    代码: % All-Pole IIR filter to Lattice structure filter a = [1, 13/24, 5/8, 1/3]; K = dir2latc(a) % To ...

  9. Django的MultipleChoiceField处理小技巧

    1.如果遇到多选择的,在收到数据时一般需要做处理 tag_id = fields.MultipleChoiceField( choices=[], widget=widgets.CheckboxSel ...

  10. c++ template不能有cpp

    c++的template只能把生命和定义都放在.h文件里,不然会出错