目录
一、is 与 ==
二、深浅拷贝
三、生成器(generator)
1、列表推导式
2、列表生成器
3、函数生成器
四、迭代器
可迭代对象
五、闭包(closure)
六、装饰器
一、is 与 ==
==
比较运算符。是用来比较两个值的大小的。(比较两个对象的值是否相同)
is
是一个关键字。是用来比较两个变量的内存地址。(比较两个对象的引用是否相同)相当于使用id
获取内存地址后再比较。
id() ,是Python的一个内置函数,返回对象的唯一标识,用于获取对象的内存地址。
注意:在python中,存在一个
小整型缓冲区
。在这个区域内的整数,只会存在一份,所以is
和==
是一致的。小整型缓冲区
默认范围是[-5, 256]区间所有整数。注意:字符串也存在一个字符串常量池,用来保存第一个出现的
单词
,如果再次要使用这个单词,则会直接从常量池中获取这个单词对应的内存地址,所以,字符串往往只有一份,被成为字符常量。
is 和 == 哪个效率高?
相比之下,
is
比较的效率更高,因为它只需要判断两个对象的id是否相同即可。而
==
则需要重载__eq__ 这个函数,遍历变量中的所有元素内容,逐次比较是否相同。因此效率较低
二、深浅拷贝
-
引用传递
引用传递:将对象的地址复制给其他变量,因此会有多个引用指向同一个对象。
-
浅拷贝
将对象的第一层属性进行拷贝,得到一个新的对象,注意:如果存在子对象,不会拷贝
浅拷贝的是对象的引用,如果原对象改变,相应的拷贝对象也会发生改变
-
深拷贝
将对象采用递归方式,逐层拷贝,最后得到完成不同的对象。
深拷贝对象中的每个元素,拷贝对象和原有对象不在有关系,两个是独立的对象
拷贝:指的是对象拷贝(复制)。
所谓深拷贝呢,就是重新分配一个内存空间(新对象),将原对象中的所有元素通过递归的方式进行拷贝到新对象中。在Python中 通过
copy.deepcopy()
来实现深拷贝。
三、生成器(generator)
1、列表推导式
python提供了一种快速生成列表的方式。
[i for i in range(10)]
[i for i in range(10) if i % 2 == 0]
[i * j for i in range(10) for j in range(9)]
2、列表生成器
列表生成器实在列表推导式的基础上,优化内存得到的。
将列表推导式,就行优化,使得所有不在全部加载内存,而是通过一段算法,一次只得到一个元素。
将列表推导式中的[]
变成()
即可。
优点:节约内存。
3、函数生成器
常规的方式,如果要生成一个复杂的列表,通过要使用函数。
而如果这个列表比较大,使用函数也存在一个浪费内存问题,如何解决这个——函数生成器。
函数生成器:和列表生成器很像,就是该函数不会再一次生成所有的值,而是逐个生成。
yield关键字使生成器函数执行暂停,
yield
关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return
关键字。一旦遇到
yield
表达式,生成器的代码将被暂停运行,直到生成器的next()
方法被调用。每次调用生成器的next()
方法时,生成器都会恢复执行,直到达到以下某个值
def fibonacii(n):first, second = 1, 2for _ in range(n):yield firstfirst, second = second, first + secondnums = fibonacii(5)
print(nums)
# print(next(nums))
# print(nums.__next__())for num in nums:print(num, end=',')
注意:
如果函数中出现了yield关键字,该函数会自动转换为一个函数生成器。
返回值就是这个生成器,调用函数,函数不会执行,而是转换为这个生成器
next方法获取每一次生成器值的时候,函数才会执行
yield也存在类似return的功能,函数遇到yield,立刻返回yield的值
等下一次next时,会自动从yield后面一行代码继续执行
四、迭代器
——迭代器是一个包含数个值的对象,迭代器是可迭代的对象,这意味着可遍历所有值
——在python中,能够被全局函数next()
,不断地返回下一个元素的对象,被称为迭代器。
==>生成器是一种迭代器
from collections.abc import Iterable, Iterator
b = (i for i in range(9))
isinstance(b, Iterator)ls = [1,2,34,10,5,566]
isinstance(ls, Iterator)
可迭代对象
在python,能被for循环,迭代获取每一个子元素的这种对象,被称为可迭代对象。
列表,元组,字典和集合都是可迭代的对象。 它们是可迭代的容器,可以从中获得迭代器,所有这些对象都有一个iter()
方法,该方法用于获取迭代器。
可使用
collections.abc
包中Iterator
类型进行判断,结合isinstance
全局函数,完成判断。from collections.abc import Iterable, Iteratorls = [1,2,34,10,5,566] isinstance(ls, Iterable)# 可以使用其他类型完成测试,只有返回True的,才是可迭代对象,能够被for循环,获取子元素
总结:
生成器就是迭代器
迭代器不一定是生成器
迭代器一定能够被for循环迭代
可迭代对象也能够被for循环迭代
可迭代对象不一定是迭代器
迭代器一定是可迭代对象
使用全局函数
iter
将可迭代对象转换为迭代器
五、闭包(closure)
——能够访问其他函数内部变量(局部变量)的函数被称为闭包
闭包是弱数据类型编程语言所特有的现象
闭包一句话概括就是在函数中再嵌套一个函数,并且引用外部函数的变量。
def a():name = "ljh"def b():print(name)def a():name = "ljh"def b():print(name)return bres = a()
res()
闭包让外部函数常驻内存,导致垃圾不能够及时释放,但是它让局部变量变成了全局变量,所以尽量不要使用闭包,闭包在js里用的比较广泛,在Python里比较少,会在装饰器里面用
闭包优点:将局部变量全局化,使得局部变量存在了全局的生命周期。
闭包缺点:常驻内存,可能会引起内存溢出
六、装饰器
装饰器就是一个闭包,装饰器是闭包的一种应用。
——作用:在不用更改原函数(基于OCP原则)的代码前提下给函数增加新的功能。
使用时,再需要的函数前加上 @新功能函数名 即可
@符号是装饰器的语法糖
def check(fn):# 装饰器函数的内部函数,会被返回称为被装饰的函数def inner(username, password, *args, **kwargs):print("xxxx 登录了")fn(username, password, args, kwargs)print("xxxx 退出了")return inner@check
def login(username, password, *args, **kwargs):if password == '123456' and username == 'admin':print("登录成功了")print("恭喜你")else:raise Exception("对不起,登录失败")login("admin", "123456")