python学习生涯 day3-5


0 global和nonlocal关键字

python学习生涯 day3-5

注意:global是把该变量声明为全局变量,而nonlocal是把该变量声明为上一级外部函数的局部变量

x = -1

def outer():
x = 0

def inner():
nonlocal x
x = 1
print('inner:', x)

inner()
print('outer:', x)

outer()
print('global:', x)!

python学习生涯 day3-5

x = -1

def outer():
x = 0

def inner():
global x
x = 1
print('inner:', x)

inner()
print('outer:', x)

outer()
print('global:', x)

python学习生涯 day3-5

1 可迭代协议和迭代器协议

可迭代协议:凡是含有__iter__方法的都是可迭代的,(在python中,可迭代的数据类型有字符串,列表,元组,字典,集合,枚举,range等,int和布尔类型不包含__iter__方法)
迭代器协议:凡是含有__iter__和__next__方法的都是迭代器
For循环的实质就是在调用__next__方法
l = [1, 2, ‘8hjg’, 0]
for i in l:
pass
‘’’

for循环的实质为:

    iterator = l.iter()#可迭代的数据类型使用__iter__方法后,就返回了一个迭代器iterator.next()#对于迭代器使用__next__方法后,相当于从迭代器中一个一个取值当出现false后,执行结束
    ‘’’
    迭代器的优势:
    a)迭代器中的值会一个一个的被取出
    b)节省内存空间,循环一次产生一个变量,而不是一次性全部产生
    尤其是对于文件句柄和range()而言,特别节省内存空间

2生成器

生成器的本质还是迭代器,凡是含有yield关键字的函数都是生成器函数
0)yield不能与return混用,且必须写在函数内部
1)生成器函数在被执行后会返回一个生成器作为返回值 ,而函数内部的语句并不会被执行
2)一个简单的生成器函数的例子

python学习生涯 day3-5
打印结果如下图:
python学习生涯 day3-5
简单介绍一下return和yield的区别吧:
当一个程序执行到return时,程序结束,return之后的语句不会再执行,换句话说,return就是程序结束的标志,而yield不会引起程序结束,当程序运行到yield时,相当于暂停了,如果下一次又调用函数,需要执行yield时,接着上次暂停的地方继续执行(不知道这么理解对不对)
我个人喜欢用一些生活中的例子来进行类比:
执行程序相当于在跑马拉松,当出现return时,相当于选手退出比赛,当出现yield时,相当于选手暂停休息了一会,当生成器函数被再次调用时,选手又接着上次暂停的地方继续开始跑,直到出现下一个yield
说到跑步的例子,我就不得不再说一下break和continue的区别了:
这也不能说是我思维混乱,只能说思维比较跳跃吧
由于break和continue一般是在循环中使用的,所以类比成在操场跑圈吧
break相当于选手直接退赛,不再参与跑圈这一运动,而continue相当于选手放弃了这圈中没有跑完的这一部分,直接从下一圈的起点开始跑

3 生成器进阶知识

0)一个实例:

def genreatoion():
print(123)
count = yield 1
print('=====', count)
yield 2

g = genreatoion()
ret = g.__next__()
print(ret)
ret = g.send('hello')
print(ret)

python学习生涯 day3-5

我们注意到,在上面这段代码中,我们使用了send方法,而且不同于之前的yield形式,我们对yield进行了一个赋值,
注意:# send和__next__功能相似,send在获取下一个值的时候,将上一个yield位置赋值给一个变量
使用send的两个注意点:
第一次使用生成器函数时,必须先使用__next__函数,因为send要获取上一个yield位置,经过验证,可以用send(None)来代替 # 最后一个yield不接受外部的值
1)一个移动平均值的例子:

	def average():
ave = 0
sum = 0
count = 0
while True:
num = yield ave
sum += num
count += 1
ave = sum/count

g = average()
g.__next__()
ave1 = g.send(10)
ave1 = g.send(20)
print(ave1)

这个代码虽然很简单,但是在while中,num = yield ave这条语句的位置很重要,如果这条语句放在循环的最后一句,执行就会出现错误,因为num没有被定义

2)我们也可以把g.__next__这条语句放在装饰器中

def init(func):

def inner(*args, **kwargs):
ret1 = func(*args, **kwargs)
ret1.__next__()
return ret1
return inner

@init#init = init(average)
def average():
ave = 0
sum = 0
count = 0
while True:
num = yield ave
sum += num
count += 1
ave = sum/count

g = average()
ave1 = g.send(10)
ave1 = g.send(20)
print(ave1)

这段代码相当于装饰器和生成器进阶的融合,一定要好好理解

4yield from 语句

0)在python2中,如果要逐个获取字符串中每一个变量,只能使用如下方式

def geration():
a = '67890'
b = '12345'
for i in a:
yield I
for i in b:
yield i

g = geration()
for i in g:
print(i)

1) 在python3中,更新了yield from语句,它的使用如下;

def geration():
a = '67890'
b = '12345'
yield from a
yield from b

g = geration()
for i in g:
print(i)

两种方法的结果都是一样的,所以在今后的学习中,遇到了yield from语句,一定不要惊讶

python学习生涯 day3-5

5 列表推导式和生成器表达式

0)列表推导式

egg_list = ['鸡蛋%d' % i for i in range(10)]
print(egg_list)

python学习生涯 day3-5
1)生成器表达式

egg_list1 = ('鸡蛋%d' % i for i in range(10))
print(egg_list1)
for i in egg_list1:
print(i)

python学习生涯 day3-5
生成器表达式返回的永远是一个生成器,只有对生成器中的每一个元素进行输出,才能达到我们想要的效果

两者的区别:

0)列表推导式使用的是[] 而生成器表达式使用的是()
1) 与列表推导式相比较,生成器表达式几乎不占用内存
因为它一次取一个,而列表推导式一次全部都取出来了
2)生成器表达式返回的是一个生成器,这也是最关键的一点

6 各种列表推导式

0)30以内能被3整除的数的平方

egg_list = [i*i for i in range(30) if i % 3 == 0]
print(egg_list)

注意:一个完整的列表推导式要有if,if的作用相当去筛选,没有if相当于遍历
python学习生涯 day3-5
1)嵌套列表中,e出现2次的名字python学习生涯 day3-5
先for大列表再for小列表python学习生涯 day3-5

7 字典推导式

0)将字典的key和value对调

mask = {'a': 10, 'b': 20}
antimask = {mask[k]: k for k in mask}
print(antimask)

python学习生涯 day3-5

这里简单介绍一下什么是可哈希的,什么是不可哈希的?
不严谨但易懂的解释:
一个对象在其生命周期内,如果保持不变,就是hashable(可哈希的)。
hashable ≈ imutable 可哈希 ≈ 不可变
在Python中:
list、set和dictionary 都是可改变的,比如可以通过list.append(),set.remove(),dict[‘key’] = value对其进行修改,所以它们都是不可哈希的;
而tuple和string是不可变的,只可以做复制或者切片等操作,所以它们就是可哈希的。
总结一下,可哈希的数据类型有元组,字符串,以及字典的键

8 集合推导式

0)寻找集合中每一个元素的平方

suqrat = {i*i for i in [1, -1, 2]}
print(suqrat)

python学习生涯 day3-5

注意:集合本身具有去重功能

为什么没有元组推导式呢?其实这是一个很有趣的问题!!!
我在最后会公布答案

9 直接赋值,浅拷贝和深拷贝

直接赋值:相当于给原对象新贴了一个标签

a = 1
b = a
print('a:', id(a))
print('b:', id(b))

python学习生涯 day3-5


浅拷贝:a 和 b 是独立的对象,但他们的子对象还是指向统一对象(是引用)。
使用浅拷贝和深拷贝时,需要引入copy模块,即要在开始前加上import copy

import copy
a = [1, {1, 2, 3}]
b = copy.copy(a)

a.append(2)

print(a, b)
a[1].add(4)
print(a, b)

python学习生涯 day3-5

深拷贝:a和b是独立的对象,他们的子对象也是独立的对象

import copy
a = [1, {1, 2, 3}]
b = copy.deepcopy(a)

a.append(2)

print(a, b)
a[1].add(4)
print(a, b)

python学习生涯 day3-5


有人把直接赋值比喻成:旧瓶装旧酒;浅拷贝比喻成:新瓶装旧酒;深拷贝比喻成:新瓶装新酒,我觉得很有意思

知道为什么没有元组推导式吗?
因为
因为元组的符号是(),这个符号已经被生成器表达式用了,哈哈哈!

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

python学习生涯 day3-5

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » python学习生涯 day3-5
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏