一、装饰器(decorator)

  • 装饰器本质上也是函数,目的是为其他函数添加附加功能(装饰其他函数)
  • Python通过使用装饰器来达到代码的开放与封闭。

原则:

  1. 不能修改被装饰函数的源代码。
  2. 不能修改被装饰函数的调用方式。

我们现在有个需求:写一个计时器来统计每个函数执行的时间长度,满足上面的2个原则。

  • 实现一:
  1. import time
  2. def timer(func):
  3. start_time = time.time()
  4. func()
  5. stop_time = time.time()
  6. print("The function run time is %s" % (stop_time-start_time))
  7. return func
  8. def f1():
  9. print("This is function F1")
  10. time.sleep(1)
  11. timer(f1)

上述方法虽然可以实现需求,但是它却改变了原函数f1的调用方式,所以不满足第2个原则。

  • 我们下面使用装饰器来实现:
  1. import time
  2. def timer(func):
  3. def deco():
  4. start_time = time.time()
  5. func()
  6. stop_time = time.time()
  7. print("The func run time is %s" % (stop_time-start_time))
  8. return deco
  9. @timer
  10. def f1():
  11. print("This is function F1")
  12. time.sleep(1)
  13. f1()

装饰器使用“@+函数名”的语法,当代码运行到@timer的时候,会把下面被装饰的函数f1做为自己的参数,相当于:func = f1,当f1()执行时,实际上执行的是deco()。

  • 当被装饰的函数有参数时我们怎么实现呢?
  1. 参数固定时:
  1. def login(func):
  2. def deco(user):
  3. print("[装饰器]正在验证登录:")
  4. func(user)
  5. return deco
  6. @login
  7. def wel(user):
  8. print("Welcome %s to login the page!" % user)
  9. wel("huyd")

2.参数不固定时:

  1. def login(func):
  2. def deco(*args,**kwargs):
  3. print("[装饰器]正在验证登录:")
  4. func(*args,**kwargs)
  5. return deco
  6. @login
  7. def wel(*args,**kwargs):
  8. print("Welcome {} to login the page!".format(*args,**kwargs))
  9. wel("huyd")
  • 当被装饰的函数有返回值时,又该怎么实现呢?
  1. def login(func):
  2. def deco(*args,**kwargs):
  3. print("[装饰器]正在验证登录:")
  4. res = func(*args,**kwargs)
  5. return res # 此处应该将被装饰函数的返回值return
  6. return deco
  7. @login
  8. def wel(*args,**kwargs):
  9. print("Welcome {} to login the page!".format(*args,**kwargs))
  10. return "sucessful" # 被装饰的函数有返回值
  11. wel = wel("huyd")
  12. print(wel)
  • 装饰器也可以有自己的参数
  1. def deco_fun1():
  2. print("装饰器功能1")
  3. def deco_fun2():
  4. print("装饰器功能2")
  5. def deco(deco_fun): # 第1层传入装饰器参数(这里只传入了1个参数,也可传入多个)
  6. def outer(main_fun): # 第2层传入被装饰的函数名
  7. def inner(): # 第3层传入被装饰函数的参数
  8. deco_fun()
  9. main_fun()
  10. return inner
  11. return outer
  12. @deco(deco_fun1) # 这样就使用了装饰器deco功能1
  13. def index():
  14. print("我是主程序")
  15. index()

需求:使用装饰器写一个简单的用户认证功能,当登录index页面时使用本地验证用户名,登录home页面时使用LDAP验证。

  1. user,passwd = 'huyd','123'
  2. def auth(auth_type): # 判断装饰器的参数
  3. def outer_wrapper(func):
  4. def wrapper(*args,**kwargs):
  5. if auth_type == "local":
  6. username = input("Username:").strip()
  7. password = input("Password:").strip()
  8. if username == user and password == passwd:
  9. print("\033[32;1mLogin successful!\033[0m")
  10. res = func(*args,**kwargs)
  11. return res
  12. else:
  13. print("\033[31;1mInvalid username or password!\033[0m")
  14. elif auth_type == "ldap":
  15. print("Home page must be LDAP type Login!")
  16. return wrapper
  17. return outer_wrapper
  18. @auth(auth_type="local")
  19. def index():
  20. print("Welcome to index page!")
  21. return "Index"
  22. @auth(auth_type="ldap")
  23. def home():
  24. print("Welcome to home page!")
  25. return "Home"
  26. # index() # 进入index页面时使用本地验证登录
  27. home() # 进入home页面时使用LDAP验证登录

二、生成器(generator)& 迭代器(iterator)

  • 迭代器是访问集合中元素的一种方式,迭代器 object从集合中的第一个元素开始访问,知道所有的元素被访问完成.
  • 所以迭代器的特点是:只能往前,不能后退
  • 迭代器的优点:不需要提前准备整个迭代器中的所有元素,仅仅迭代到某个元素时才计算该元素,而之前或者之后,元素可以不存在或者销毁.因为这个特点,迭代器特别适合遍历文件比较大或者无限的集合.
  • 总结下迭代器 iter()的特点吧:
  1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存

迭代器是用__next__()来取值的,来看个例子吧:

  1. gen = iter([1,2,3])
  2. # 取值方法一:
  3. print(gen.__next__())
  4. print(gen.__next__())
  5. print(gen.__next__())
  6. print(gen.__next__()) #再取值就会报错
  7. # 取值方法二:
  8. for i in gen:
  9. print(i)

能被for直接循环的都是可迭代对象,如列表,字典等。判断一个对象是不是可迭代对象,可以使用isinstance(*, Iterable)来判断。

生成器在被调用的时候返回一个迭代器。生成器有个标志性的语法yield。

当生成器被调用时,yield返回一个值,并记住当前位置,下一次调用时,从yield下一句语句运行返回下一个值。

  1. def catch_mony(amount):
  2. while amount > 0:
  3. amount -= 100
  4. print("又来取钱了!")
  5. yield "给你100吧,剩余:{}".format(amount)
  6. atm = catch_mony(500)
  7. print(type(atm))
  8. print(atm.__next__())
  9. print(atm.__next__())
  10. print("去看电影!。。。")
  11. print(atm.__next__())
  12. ======================================
  13. 运行结果:
  14. <class 'generator'>
  15. 又来取钱了!
  16. 给你100吧,剩余:400
  17. 又来取钱了!
  18. 给你100吧,剩余:300
  19. 去看电影!。。。
  20. 又来取钱了!
  21. 给你100吧,剩余:200

此外,yield还有实现在单线程模式下实现并发运算的效果。如下例:

  1. import time
  2. def consumer(name):
  3. print("{}准备吃包子啦!".format(name))
  4. while True:
  5. baozi = yield # yield也可以用于接收值
  6. print("第{}次的包子来了,被{}吃掉了!".format(baozi, name))
  7. def producer(name):
  8. c1 = consumer('A')
  9. c2 = consumer('B')
  10. c1.__next__()
  11. c2.__next__()
  12. print("{}准备开始做包子了!".format(name))
  13. for i in range(1, 11):
  14. time.sleep(1)
  15. print("{}第{}次做了两个包子。".format(name, i))
  16. c1.send(i) # 将i的值传给yield
  17. c2.send(i) # 将i的值传给yield
  18. producer("老板")

三、Json & pickle 数据序列化

用于序列化的两个模块:

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换
  • Json模块提供了四个功能:dumps、dump、loads、load
  • pickle模块提供了四个功能:dumps、dump、loads、load
  1. import json
  2. data = {'k1':123,'k2':'Hello'}
  3. # json.dumps 将数据通过特殊的形式转换为所有程序语言都认识的字符串
  4. j_str = json.dumps(data)
  5. print(type(j_str),j_str)
  6. # json.loads 将字典形式的字符串转换为字典格式
  7. j_dict = json.loads(j_str)
  8. print(type(j_dict),j_dict)
  9. # json.dump 将数据通过特殊的形式转换为所有程序都认识的字符串,并写入文件
  10. with open('result.json','w') as f:
  11. json.dump(data,f)
  12. #######################################################################
  13. import pickle
  14. # pickle.dumps 将数据通过特殊的形式转换为只有python语言认识的字符串
  15. p_str = pickle.dumps(data)
  16. print(type(p_str),p_str)
  17. # pickle.dump 将数据通过特殊的形式转换为只有Python语言认识的字符串,并写入文件
  18. with open('result.pk','w') as f:
  19. pickle.dump(data,f)

Python-04-基础的更多相关文章

  1. Python编程语言基础

    今天给大家讲解python语言基础~~ 01.python核心数据类型   整型数 int:整数是不带有小数部分的数字 浮点型数 float:浮点数是带有小数部分的数字(小数部分可以是0) 复数 co ...

  2. Python语言基础与应用 (P16)上机练习:基本数据类型

    本文是笔者在学习MOOC课程<Python语言基础与应用> (北京大学-陈斌)中根据上机课时的要求写下在代码 课程总链接: 中国大学MOOC B站 本节课链接 数值基本运算: 33和7+, ...

  3. Python实验报告——第2章 Python语言基础

    实验报告 [实验目的] 1.熟悉在线编程平台. 2.掌握基本的 python 程序编写.编译与运行程序的方法. [实验条件] 1.PC机或者远程编程环境 [实验内容] 1.完成第二章实例01-07,实 ...

  4. Python文件基础

    ===========Python文件基础========= 写,先写在了IO buffer了,所以要及时保存 关闭.关闭会自动保存. file.close() 读取全部文件内容用read,读取一行用 ...

  5. 3.Python编程语言基础技术框架

    3.Python编程语言基础技术框架 3.1查看数据项数据类型 type(name) 3.2查看数据项数据id id(name) 3.3对象引用 备注Python将所有数据存为内存对象 Python中 ...

  6. Python爬虫基础

    前言 Python非常适合用来开发网页爬虫,理由如下: 1.抓取网页本身的接口 相比与其他静态编程语言,如java,c#,c++,python抓取网页文档的接口更简洁:相比其他动态脚本语言,如perl ...

  7. 小白必看Python视频基础教程

    Python的排名从去年开始就借助人工智能持续上升,现在它已经成为了第一名.Python的火热,也带动了工程师们的就业热.可能你也想通过学习加入这个炙手可热的行业,可以看看Python视频基础教程,小 ...

  8. Python爬虫基础之requests

    一.随时随地爬取一个网页下来 怎么爬取网页?对网站开发了解的都知道,浏览器访问Url向服务器发送请求,服务器响应浏览器请求并返回一堆HTML信息,其中包括html标签,css样式,js脚本等.我们之前 ...

  9. 零基础学Python--------第2章 Python语言基础

    第2章  Python语言基础 2.1 Python语法特点 2.11注释 在Python中,通常包括3种类型的注释,分别是单行注释.多行注释和中文编码声明注释. 1.单行注释 在Python中,使用 ...

  10. Python学习基础笔记(全)

    换博客了,还是csdn好一些. Python学习基础笔记 1.Python学习-linux下Python3的安装 2.Python学习-数据类型.运算符.条件语句 3.Python学习-循环语句 4. ...

随机推荐

  1. java多线程-信号量

    Semaphore(信号量)是一个线程同步结构,用于在线程间传递信号,以避免出现信号丢失,或者像锁一样用于保护一个关键区域.自从 5.0 开始,jdk 在 java.util.concurrent 包 ...

  2. 很漂亮的用户登录界面HTML模板

    效果预览:http://keleyi.com/keleyi/phtml/divcss/21.htm HoverTree开源项目实现了分层后,准备实现管理员后台登录,这里先把登录界面的HTML模板整理好 ...

  3. iOS 根据字符串数目,自定义Label等控件的高度

    利用分类,NSString,增加一个方法. #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interfa ...

  4. ks

    http://www.codeproject.com/Articles/207820/The-Repository-Pattern-with-EF-code-first-Dependen

  5. Eclipse 常用快捷键 For MAC

    Eclipse 常用快捷键 For MAC Option + Command + X: 运行Command + O:显示大纲Command + 1:快速修复Command + D:删除当前行Comma ...

  6. OC 单例模式

    OC 单例模式 概念 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约 ...

  7. J2ObjC 1.0 发布,将 Java 转换为 Objective-C

    J2ObjC 是一个Google开发的开源工具,用于将Java代码转换为Objective-C代码.其目的是为了能在iOS平台上重用Android平台.web服务器端的Java代码.服务器端代码的转换 ...

  8. 解决PKIX:unable to find valid certification path to requested target 的问题

    这两天在twitter服务器上忽然遇到这样的异常: e: sun.security.validator.ValidatorException: PKIX path building failed: s ...

  9. linux top 源码分析

    /* * Copyright (c) 2008, The Android Open Source Project * All rights reserved. * * Redistribution a ...

  10. Asp.Net MVC+BootStrap+EF6.0实现简单的用户角色权限管理3

    首先在webconfig中加入下面这句代码,这个主要是用来生成数据库的连接字符串 <connectionStrings> <add name="AuthorDesignCo ...