闭包函数

闭包

闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。

额。。。这里提示一下闭包!=自闭

为函数传参的两种方式

使用参数的方式

def func(x):
print(x) func(1)
func(1)
func(1)

1

1

1

包给函数

def outter(x):
x = 1 def inner():
print(x)
return inner f = outter(1)
f()
f()
f()
# 查看闭包的元素
print(F"f.__closure__[0].cell_contents: {f.__closure__[0].cell_contents}")
1
1
1
f.__closure__[0].cell_contents: 1

装饰器

什么是装饰器

器指的是工具,而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能。

需要注意的是:

  • 装饰器本身其实是可以任意可调用的对象
  • 被装饰的对象也可以是任意可调用的对象

为什么要用装饰器

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

装饰器的实现必须遵循两大原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

装饰器的实现必须遵循两大原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

装饰器的实现必须遵循两大原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

装饰器的实现必须遵循两大原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

装饰器的实现必须遵循两大原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

怎么用装饰器

改变源代码

import time

def index():
start = time.time()
print('welcome to index')
time.sleep(1)
end = time.time()
print(F"index run time is {start-end}") index() welcome to index
index run time is -1.0008180141448975

编写重复代码

import time

def index():
print('welcome to index')
time.sleep(1) def f2():
print('welcome to index')
time.sleep(1) start = time.time()
index()
end = time.time()
print(F"index run time is {start-end}") start = time.time()
f2()
end = time.time()
print(F"f2 run time is {start-end}") welcome to index
index run time is -1.0046868324279785
welcome to index
f2 run time is -1.000690221786499

第一种传参方式:改变调用方式

import time

def index():
print('welcome to index')
time.sleep(1) def time_count(func):
start = time.time()
func()
end = time.time()
print(f"{func} time is {start-end}") time_count(index) welcome to index
<function index at 0x102977378> time is -1.000748872756958

第二种传参方式:包给函数-外包

import time

def index():
print('welcome to index')
time.sleep(1) def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
func()
end = time.time()
print(f"{func} time is {start-end}")
return wrapper # f = time_count(index)
# f() index = time_count(index) # index为被装饰函数的内存地址,即index = wrapper
index() # wrapper() welcome to index
<function index at 0x102977730> time is -1.0038220882415771

完善装饰器

上述的装饰器,最后调用index()的时候,其实是在调用wrapper(),因此如果原始的index()有返回值的时候,wrapper()函数的返回值应该和index()的返回值相同,也就是说,我们需要同步原始的index()和wrapper()方法的返回值。

import time

def index():
print('welcome to index')
time.sleep(1) return 123 def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
res = func()
end = time.time()
print(f"{func} time is {start-end}") return res
return wrapper index = time_count(index)
res = index()
print(f"res: {res}")##
welcome to index
<function index at 0x102977620> time is -1.0050289630889893
res: 123

如果原始的index()方法需要传参,那么我们之前的装饰器是无法实现该功能的,由于有wrapper()=index(),所以给wrapper()方法传参即可。

import time

def index():
print('welcome to index')
time.sleep(1) return 123 def home(name):
print(f"welcome {name} to home page")
time.sleep(1) return name def time_count(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func} time is {start-end}") return res
return wrapper home = time_count(home) res = home('egon')
print(f"res: {res}")##
welcome egon to home page
<function home at 0x102977378> time is -1.0039079189300537
res: egon

装饰器语法糖

在被装饰函数正上方,并且是单独一行写上@装饰器名

import time

def time_count(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func} time is {start-end}") return res
return wrapper @time_count # home = time_count(home)
def home(name):
print(f"welcome {name} to home page")
time.sleep(1) return name @time_count # index = time_count(index)
def index():
print('welcome to index')
time.sleep(1) return 123 res = home('egon')
print(f"res: {res}")##
welcome egon to home page
<function home at 0x102977620> time is -1.0005171298980713
res: egon

有参装饰器

import time

current_user = {'username': None}

def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs): if current_user['username']:
res = func(*args, **kwargs) return res user = input('username: ').strip()
pwd = input('password: ').strip() engine = 'file' if engine == 'file':
print('base of file')
if user == 'nick' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs) return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql')
elif engine == 'mongodb':
print('base of mongodb')
else:
print('default') return wrapper @login
def home(name):
print(f"welcome {name} to home page")
time.sleep(1) @login
def index():
print('welcome to index')
time.sleep(1) res = index()
username: nick
password: 123
base of file
login successful
welcome to index

三层闭包

import time

current_uesr = {'username': None}

def auth(engine='file'):

    def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs): if current_user['username']:
res = func(*args, **kwargs) return res user = input('username: ').strip()
pwd = input('password: ').strip() if engine == 'file':
print('base of file')
if user == 'nick' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs) return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql, please base of file')
elif engine == 'mongodb':
print('base of mongodb, please base of file')
else:
print('please base of file') return wrapper return login @auth(engine='mysql')
def home(name):
print(f"welcome {name} to home page")
time.sleep(1) @auth(engine='file')
def index():
print('welcome to index')
time.sleep(1) res = index()
username: nick
password: 123
base of file
login successful
welcome to index

由于两层的装饰器,参数必须得固定位func,但是三层的装饰器解除了这个限制。我们不仅仅可以使用上述单个参数的三层装饰器,多个参数的只需要在三层装饰器中多加入几个参数即可。也就是说装饰器三层即可,多加一层反倒无用。

装饰器叠加

def outter1(func):  # func = wrapper2
def wrapper1(*args, **kwargs): # wrapper是未来要运行的函数
print('------------')
res = func(*args, **kwargs) # func是被装饰的函数 # wrapper2
print('------------')
return res return wrapper1 def outter2(func): # func = index
def wrapper2(*args, **kwargs): # wrapper是未来要运行的函数
print('11111111111111')
res = func(*args, **kwargs) # func是被装饰的函数 # index()
print('11111111111111')
return res return wrapper2 # @outter1 # index = outter1(index)
# @outter2 # index = outter2(index) # 先运行最下面的装饰器
# # index
def index():
print('index') # index重新定义的index = outter2(index 真正的index)
index = outter2(index) # index = wrapper2
# index再一次重新定义的index = outter1(index重新定义的index,即wrapper2)
index = outter1(index) # index = wrapper1
index() # wrapper1()

兄弟自求多福!!!(切勿钻牛角尖)

迭代器

迭代器:迭代的工具。迭代是更新换代,如你爷爷生了你爹,你爹生了你,迭代也可以说成是重复,并且但每一次的重复都是基于上一次的结果来的。如计算机中的迭代开发,就是基于软件的上一个版本更新。以下代码就不是迭代,它只是单纯的重复

可迭代对象

python中一切皆对象,对于这一切的对象中,但凡有__iter__方法的对象,都是可迭代对象。

# x = 1.__iter__  # SyntaxError: invalid syntax

# 以下都是可迭代的对象

name = 'nick'.__iter__
lis = [1, 2].__iter__
tup = (1, 2).__iter__
dic = {'name': 'nick'}.__iter__
s1 = {'a', 'b'}.__iter__
f = open('49w.txt', 'w', encoding='utf-8')
f.__iter__
f.close()

迭代器对象

只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的。因此我们得找到一个方法能让其他的可迭代对象不依赖索引取值。

在找到该方法前,首先我们给出迭代器对象的概念:可迭代的对象执行__iter__方法得到的返回值。并且可迭代对象会有一个__next__方法。

# 不依赖索引的数据类型迭代取值
dic = {'a': 1, 'b': 2, 'c': 3}
iter_dic = dic.__iter__()
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())
# print(iter_dic.__next__()) # StopIteration:
a
b
c

for循环原理

for循环称为迭代器循环,in后必须是可迭代的对象

is = [1, 2, 3]
for i in lis:
print(i)

1

2

3

因为迭代器使用__iter__后还是迭代器本身,因此for循环不用考虑in后的对象是可迭代对象还是迭代器对象。

由于对可迭代对象使用__iter__方法后变成一个迭代器对象,这个迭代器对象只是占用了一小块内存空间,他只有使用__next__后才会吐出一个一个值。如lis = [1,2,3,4,5,...]相当于一个一个鸡蛋,而lis = [1,2,3,4,5,...].__iter__相当于一只老母鸡,如果你需要蛋,只需要__next__即可。

python-day13(正式学习)的更多相关文章

  1. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  2. Requests:Python HTTP Module学习笔记(一)(转)

    Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...

  3. 从Theano到Lasagne:基于Python的深度学习的框架和库

    从Theano到Lasagne:基于Python的深度学习的框架和库 摘要:最近,深度神经网络以“Deep Dreams”形式在网站中如雨后春笋般出现,或是像谷歌研究原创论文中描述的那样:Incept ...

  4. Comprehensive learning path – Data Science in Python深入学习路径-使用python数据中学习

    http://blog.csdn.net/pipisorry/article/details/44245575 关于怎么学习python,并将python用于数据科学.数据分析.机器学习中的一篇非常好 ...

  5. (转载)Python装饰器学习

    转载出处:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方 ...

  6. 正式学习React(五) react-redux源码分析

    磨刀不误砍柴工,咱先把react-redux里的工具函数分析一下: 源码点这里  shallowEqual.js export default function shallowEqual(objA, ...

  7. 正式学习React(一) 开始学习之前必读

    为什么要加这个必读!因为webpack本身是基于node环境的, 里面会涉及很多路径问题,我们可能对paths怎么写!webpack又是怎么找到这些paths的很迷惑. 本文是我已经写完正式学习Rea ...

  8. python网络爬虫学习笔记

    python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...

  9. Python装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- ...

  10. Python的基础学习(第二周)

    模块初始 sys模块 import sys sys.path #打印环境变量 sys.argv#打印该文件路径 #注意:该文件名字不能跟导入模块名字相同 os模块 import os cmd_res ...

随机推荐

  1. TTTTTTTTTTTT POJ 2112 奶牛与机器 多重二分匹配 跑最大流 建图很经典!!

    Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 15682   Accepted: 5597 ...

  2. Moco 详解

    一.下载及安装: 运行环境: JAVA环境 linux 下载地址:https://github.com/dreamhead/moco 下载下来的是一个jar包,如:moco-runner-0.12.0 ...

  3. sqli-labs(39)

    0X01 这关和38关一样 ?id= and =1 正确 ?id=1 and 1=2 错误 不需要闭合 构造语法 0X02 ?id=;insert into users values(,"z ...

  4. Java密码处理

  5. python3笔记十三:python数据类型-Set集合

    一:学习内容 集合概念 集合创建 集合添加 集合插入 集合删除 集合访问 集合操作:并集.交集 二:集合概念 1.set:类似dict,是一组key的集合,不存储value 2.本质:无序和无重复元素 ...

  6. SpringBoot 2.x 使用Redis作为项目数据缓存

    一.添加依赖 <!-- 添加缓存支持 --> <dependency> <groupId>org.springframework.boot</groupId& ...

  7. erlang创建100万个进程,每一个进程花费多少时间呢?

    最近工作需要,需要先测试一下erlang启动进程的时间开销: 看了一片博客,感觉挺好的,学习erlang推荐http://www.blogjava.net/yongboy/ 于是参照他的文章里面的一个 ...

  8. 一起学vue指令之v-text

    一起学vue指令之v-text 一起学 vue指令 v-text  指令可看作标签属性 v-text的功能和v-html很相似,都是在容器标签内控制字符串内容的输出,v-text输出纯文本,而v-ht ...

  9. 全面解读php-常量及数据类型

    本文主要讲解字符串的定义方式,数据类型和常量的相关内容. 一.字符串的定义方式 1.字符串的定义方式除了单双引号外,还有一种叫 heredoc 和 newdoc  在我们需要定义很长一段儿字符串的时候 ...

  10. 详解嵌套ListView、ScrollView布局显示不全的问题

    在项目开发中,可能经常遇到嵌套ListView.ScrollView的问题,就是重写onMeasure方法.解决如下 public class ExpandListView extends ListV ...