python成长之路七-函数的进阶
1,python中,名称空间分三种:
全局命名空间
局部命名空间(临时命名空间)
内置名称空间
2,作用域(两种):
1,全局作用域 包含:全局名称空间 内置名称空间
2,局部作用域 包含:局部命名空间
2.1,取值顺序:
就近原则:局部名称空间 --> 全局名称空间 --> 内置名称空间 单向从小到大范围
2.2, 加载顺序:
内置名称空间 --> 全局名称空间(当程序执行时) -- > 局部名称空间(当函数调用的时候)
3,函数的嵌套:
def func1():
print(111)
def func2():
print(222)
func1()
print(333)
print(666)
func2()
print(555)
例子1
def func1():
print(222)
def func2():
print(333)
print(111)
func2()
print(666)
func1() # 执行结果:
222 111 333 666
例子2
4,global nonlocal
局部名称空间对全局名称空间的变量可以引用,但是不能改变。
count = 1
def func1():
count = 2
print(count)
func1()
count = 1
def func1():
# count = 3
count = count + 1 # local variable 'count' referenced before assignment
print(count)
func1()
报错
报错原因: 如果你在局部名称空间 对一个变量进行修改,那么解释器会认为你的这个变量在局部中已经定义了,但是对于上面的例题,局部中没有定义,所以他会报错,
global
1,在局部名称空间声明一个全局变量。
2,在局部名称空间声明可以对全局变量进行修改。
count = 1
def func1():
global count
count = count + 1
print(count)
func1()
print(count)
修改
nonlocal
1,子函数对父函数的变量进行修改。
2,此变量不能是全局变量
3,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
def func1():
count = 666
def inner():
print(count)
def func2():
nonlocal count
count += 1
print("func2",count)
func2()
print("inner",count)
inner()
print("funcl",count)
func1() # 运行结果:
666
func2 667
inner 667
funcl 667
global
5,函数的应用
1,函数名就是函数的内存地址。
def func():
pass
print(func) # <function func at 0x05958660>
2,函数名可以作为变量。
def func1():
print(666)
f1 = func1
f2 = f1
f2()
3,函数名可以作为函数的参数。
def func():
print(666)
def func1():
func()
def func2(x):
x()
func2(func1)
4,函数名可以当作函数的返回值。
def wraaper():
def inner():
print("inner")
return inner
ret = wraaper()
ret()
5,函数名可以当作为容器类类型的元素。
def func1():
print("in func1")
def func2():
print("in func2")
def func3():
print("in func3")
def func4():
print("in func4")
l1 = [func1,func2,func3,func4]
for i in l1:
i()
向上面的函数名这种,第一个类对象。
6,globals() locals()
1,globals() 返回全局变量的一个字典。
2,locals() 返回当前位置的局部变量的字典。
def funcl():
a = 2
b = 3
# print(globals())
# print(locals())
def inner():
c = 5
d = 6
print(globals())
print(locals())
inner()
print(globals())
print(locals())
funcl()
7,闭包
--内层函数对外层函数的变量(非全局变量)的引用,并返回。这样就形成了闭包。
1,迭代器的条件:
1,必须要有函数嵌套。
2,内层函数必须要引用外层函数中的变量(不能是全局变量)。
3,外层函数必须返回内部中的函数名(引用)。def wraaper():
n = 1
def inner():
nonlocal n
n += 1
return n
# inner()
return inner
f = wraaper()
print(f())
print(f())
闭包
2,闭包的作用:
当程序执行时,遇到了函数执行,他会在内存开辟一个空间,局部名称空间,
如果这个函数内部形成了闭包,
那么他就不会随着函数的结束而消失。
# 1,写装饰器的时候用。
# 2,写爬虫的时候用。 from urllib.request import urlopen def index():
url = "http://www.xiaohua100.cn/index.html"
def get():
return urlopen(url).read()
return get xiaohua = index() # get
content = xiaohua() # get()
content = xiaohua() # get()
print(content.decode('utf-8'))
作用
8,迭代器
1,可迭代对象
对象内部含有__iter__方法的就是可迭代对象。
可迭代对象满足可迭代协议。
2,判断是否是可迭代对象。
dic = {"name":"alex"}
print('__iter__' in dir(dic))
方法一
from collections import Iterable
from collections import Iterator
print(isinstance("alex",Iterable))
print(isinstance('alex',Iterator))
print(isinstance("alex",str))
方法二
3,可迭代对象 vs 迭代器
可迭代对象不能取值,迭代器是可以取值的。
可迭代对象 可以转化成迭代器。
lis = [1,2,3] # 可迭代对象
itet = lis.__iter__() #迭代器
itet = iter(lis) # 迭代器
print(itet)
可迭代器如何取值?
next一次,取值一次
1,可迭代对象不能取值,迭代器是可以取值的。
2,迭代器非常节省内存。
3,迭代器每次只会取一个值。
4,迭代器是单向的从上至下地取值,一条路走到头。
1,迭代器原理
1,将可迭代对象转化成迭代器。
2,调用__next__方法取值。
3,利用异常处理停止报错。
s1 = "asdfg"
iter1 = s1.__iter__()
while 1:
try:
print(iter1.__next__())
except StopIteration:
break
s1 = "asdfg" # l1 = [i for i in range(100)]
# print(11) ret = (i for i in range(10000))
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
9, 生成器
--就是自己python用代码写的迭代器,生成器的本质就是迭代器。
1,构建一个生成器的两种方式:
1,通过生成器函数。
2,生成器表达式。
生成器函数:
def func1(x):
x += 1
return x
func1(5) # 函数的执行命令,并且接受函数的返回值
print(func1(5))
函数
def func1(x):
x += 1
print(111)
print(111)
print(111)
yield x
x += 2
print(222)
yield "alex"
x += 3
g_obj = func1(5) # 生成器函数对象
# print(g_obj)
# print(g_obj.__next__())
print(g_obj.__next__())
生成器函数
一个 naxt 对应一个 yield
yield 将值返回给生成器对象 .__next__()
yield 和 return区别
return 结束函数,给函数的执行者返回值
yield 不会结束函数,一个next 对应一个yield,给生成器对.__next__()返回值。
生成器函数 和 迭代器 区别
1,自定制的区别
# li = [1,2,3,4,5]
# li.__iter__() def func1(x):
x += 1
yield x
x += 3
yield x
x += 5
yield x
g1 = func1(5)
print(g1.__next__())
print(g1.__next__())
print(g1.__next__())
区别1
2,内存级别的区别
迭代器是需要可迭代对象进行转化。可迭代对象非常占内存。
生成器直接创建,不需要转化,从本质就节省内存。
def func1():
for i in range(10000):
yield i g1 = func1()
for i in range(50):
print(g1.__next__()) # ————————————————————————
def func1():
print(1)
count = yield 6
print(count)
print(2)
count1 = yield 7
print(count1)
print(3)
yield 8 g = func1()
next(g)
g.send("alex")
# g.send("太白")
print(g.__next__())
区别二
send 与 naxt 区别
send与next一样,也是对生成器取值(执行一个yield)的方法。
send可以给上一个yield传值。
第一次取值永远都是next。
最后一个yield永远也得不到send传的值。
# 函数
def cloth1(n):
for i in range(n+1):
print("衣服%s号" % i)
cloth1(1000)
# --------------------------------
# 生成器函数
def cloth1(n):
for i in range(1,n+1):
yield ("衣服%s号" % i)
g = cloth1(1000)
for i in range(50):
print(g.__next__())
# for i in range(50):
# print(g.__next__())
函数 vs 生成器
列表推导式:
-- 一行代码几乎搞定你需要的任何的列表。
优点:一行解决,方便
缺点:容易着迷,不易排错,不能超过三次循环。
列表推导式不能解决所有列表问题,所以不要太刻意用。
循环模式 [变量(加工后的变量)for 变量 initerable]
l = [i for i in range(1,101)]
print(l) l2 = print(["python%s期" % i for i in range(1,11)]) print([i*i for i in range(1,11)])
循环模式
筛选模式 [变量(加工后的变量)in iterable if 条件]
l3 = [i for i in range(1,31) if i % 2 == 0]
print(l3) print([i for i in range(1,31) if i % 3 == 0]) print([i**2 for i in range(1,31) if i % 3 == 0]) names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
# 请选出名字中带两个e的 print([j for i in names for j in i if j.count("e") == 2])
筛选模式
生成器表达式: 将列表推导式的 [ ] 换成 ( ) 即可。
g = (i for i in range(100000))
print(g)
print(g.__next__())
print(g.__next__())
for i in range(20): # 循环取取值
print(g.__next__())
生成器表达式
mcase = {"a":10,"b":34}
mcase_frequency = {mcase[k]: k for k in mcase} # 将键值对反转
print(mcase_frequency)
元组表达式
squared = {x**2 for x in [1,-1,2]} # 将集合去重
print(squared)
集合表达式
python成长之路七-函数的进阶的更多相关文章
- python成长之路六-函数的初识
定义函数 我们现学已知的python函数有<内置函数> 而我们现在要学的是<自定义函数> 1,def 定义一个函数 def name(): # 后接函数名 冒号 pass 2 ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- 【Python成长之路】Python爬虫 --requests库爬取网站乱码(\xe4\xb8\xb0\xe5\xa)的解决方法【华为云分享】
[写在前面] 在用requests库对自己的CSDN个人博客(https://blog.csdn.net/yuzipeng)进行爬取时,发现乱码报错(\xe4\xb8\xb0\xe5\xaf\x8c\ ...
- 【Python成长之路】装逼的一行代码:快速共享文件
[Python成长之路]装逼的一行代码:快速共享文件 2019-10-26 15:30:05 华为云 阅读数 335 文章标签: Python编程编程语言程序员Python开发 更多 分类专栏: 技术 ...
- python成长之路第三篇(1)_初识函数
目录: 函数 为什么要使用函数 什么是函数 函数的返回值 文档化函数 函数传参数 文件操作(二) 1.文件操作的步骤 2.文件的内置方法 函数: 一.为什么要使用函数 在日常写代码中,我们会发现有很多 ...
- Python 成长之路
Python roadmap python 基础 ... 内置常用函数.三元运算.递归 迭代器和生成器 模块和常用的模块 面向对象 对向对象进阶 网络编程 并发编程 ... 数据库 MySQL pym ...
- 我的Python成长之路---第一天---Python基础(1)---2015年12月26日(雾霾)
2015年12月26日是个特别的日子,我的Python成之路迈出第一步.见到了心目中的Python大神(Alex),也认识到了新的志向相投的伙伴,非常开心. 尽管之前看过一些Python的视频.书,算 ...
- python成长之路【第十八篇】:python模块介绍、模块导入和重载
一.模块和命名空间 一般来说,Python程序往往由多个模块文件构成,通过import语句连接在一起.每个模块文件是一个独立完备的变量包,即一个命名空间.一个模块文件不能看到其他文件定义的变量名,除非 ...
- Python成长之路第二篇(1)_数据类型内置函数用法
数据类型内置函数用法int 关于内置方法是非常的多这里呢做了一下总结 (1)__abs__(...)返回x的绝对值 #返回x的绝对值!!!都是双下划线 x.__abs__() <==> a ...
随机推荐
- 关于PHP程序员技术职业生涯规划
看到很多PHP程序员职业规划的文章,都是直接上来就提Linux.PHP.MySQL.Nginx.Redis.Memcache.jQuery这些,然后就直接上手搭环境.做项目,中级就是学习各种PHP框架 ...
- Luogu2993 FJOI2014 最短路径树问题 最短路树、长链剖分
传送门 强行二合一最为致命 第一问直接最短路+$DFS$解决 考虑第二问,与深度相关,可以考虑长链剖分. 设$f_{i,j}$表示长度为$i$,经过边数为$j$时的最大边权和,考虑到每一次从重儿子转移 ...
- Vue-初步了解vue-router的三要素:路由map 、路由视图、路由导航
安装vue-router模块 使用vue-router前要先安装vue-router库 cnpm install vue-router –save 使用vue-router vue-router有三个 ...
- Artificial Intelligence Computing Conference(2018.09.12)
时间:2018.09.12地点:北京国际饭店会议中心
- 控制反转IOC与依赖注入DI - 理论篇
学无止境,精益求精 十年河东十年河西,莫欺少年穷 昨天是五一小长假归来上班的第一天,身体疲劳,毫无工作热情.于是就看看新闻,喝喝茶,荒废了一天 也就在昨天,康美同事张晶童鞋让我学习下IOC的理论及实现 ...
- 在平衡树的海洋中畅游(四)——FHQ Treap
Preface 关于那些比较基础的平衡树我想我之前已经介绍的已经挺多了. 但是像Treap,Splay这样的旋转平衡树码亮太大,而像替罪羊树这样的重量平衡树却没有什么实际意义. 然而类似于SBT,AV ...
- Nginx基于TCP/UDP端口的四层负载均衡(stream模块)配置梳理
通过我们会用Nginx的upstream做基于http/https端口的7层负载均衡,由于Nginx老版本不支持tcp协议,所以基于tcp/udp端口的四层负载均衡一般用LVS或Haproxy来做.至 ...
- main函数是必须的吗
研究实验4 研究过程: 问题引出:C语言编程非得用主函数main吗,不用是否可以? 对此问题进行研究,用tc.exe书写代码如下: 图1 没有main函数的c程序 对其进行编译,链接发现,编译阶段可 ...
- PairProject——结对编程
成员:12061162 王骜 12061225 钟毅恒 一.合作过程中的照片 . 二.结对编程的优缺点 优点: 1)在编程过程中,任何一段代码都不断地复审,同时避免了将写代码的责任抛给一个人的问题 ...
- 第三个Sprint冲刺第七天(燃尽图)