1,python中,名称空间分三种:

  1. 全局命名空间

  2. 局部命名空间(临时命名空间)

  3. 内置名称空间

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成长之路七-函数的进阶的更多相关文章

  1. python成长之路六-函数的初识

    定义函数 我们现学已知的python函数有<内置函数> 而我们现在要学的是<自定义函数> 1,def  定义一个函数 def name(): # 后接函数名 冒号 pass 2 ...

  2. (转)Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...

  3. 【Python成长之路】Python爬虫 --requests库爬取网站乱码(\xe4\xb8\xb0\xe5\xa)的解决方法【华为云分享】

    [写在前面] 在用requests库对自己的CSDN个人博客(https://blog.csdn.net/yuzipeng)进行爬取时,发现乱码报错(\xe4\xb8\xb0\xe5\xaf\x8c\ ...

  4. 【Python成长之路】装逼的一行代码:快速共享文件

    [Python成长之路]装逼的一行代码:快速共享文件 2019-10-26 15:30:05 华为云 阅读数 335 文章标签: Python编程编程语言程序员Python开发 更多 分类专栏: 技术 ...

  5. python成长之路第三篇(1)_初识函数

    目录: 函数 为什么要使用函数 什么是函数 函数的返回值 文档化函数 函数传参数 文件操作(二) 1.文件操作的步骤 2.文件的内置方法 函数: 一.为什么要使用函数 在日常写代码中,我们会发现有很多 ...

  6. Python 成长之路

    Python roadmap python 基础 ... 内置常用函数.三元运算.递归 迭代器和生成器 模块和常用的模块 面向对象 对向对象进阶 网络编程 并发编程 ... 数据库 MySQL pym ...

  7. 我的Python成长之路---第一天---Python基础(1)---2015年12月26日(雾霾)

    2015年12月26日是个特别的日子,我的Python成之路迈出第一步.见到了心目中的Python大神(Alex),也认识到了新的志向相投的伙伴,非常开心. 尽管之前看过一些Python的视频.书,算 ...

  8. python成长之路【第十八篇】:python模块介绍、模块导入和重载

    一.模块和命名空间 一般来说,Python程序往往由多个模块文件构成,通过import语句连接在一起.每个模块文件是一个独立完备的变量包,即一个命名空间.一个模块文件不能看到其他文件定义的变量名,除非 ...

  9. Python成长之路第二篇(1)_数据类型内置函数用法

    数据类型内置函数用法int 关于内置方法是非常的多这里呢做了一下总结 (1)__abs__(...)返回x的绝对值 #返回x的绝对值!!!都是双下划线 x.__abs__() <==> a ...

随机推荐

  1. linux中断源码分析 - 中断发生(三)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 回顾 上篇文章linux中断源码分析 - 初始化(二)已经描述了中断描述符表和中断描述符数组的初始化,由于在初始 ...

  2. token令牌

    本文摘自 WebApi安全性 使用TOKEN+签名验证 首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或 ...

  3. 2-SAT超入门讲解

    Preface 说实话2-SAT的题目我都没怎么做过,所以这里讲的都是些超入门什么的 还有一些板子题,由于是暑假的时候学的所以有些我也记不清了 主要学习参考自:Mancher的课件&& ...

  4. 数列分块入门九题(三):LOJ6283~6285

    Preface 最后一题我一直觉得用莫队是最好的. 数列分块入门 7--区间乘法,区间加法,单点询问 还是很简单的吧,比起数列分块入门 7就多了个区间乘. 类似于线段树,由于乘法的优先级高于加法,因此 ...

  5. OpenTracing:开放式分布式追踪规范

    前言 想实现一个简单的追踪系统似乎是容易的,需要必要的调用链id,时间戳等:想实现一款易用不侵入代码的追踪系统就很麻烦了,需要接触CLR和IL相关知识:即使你费劲心力做出了那些,如果性能不够好,也没有 ...

  6. ASP.NET Core使用TopShelf部署Windows服务

    asp.net core很大的方便了跨平台的开发者,linux的开发者可以使用apache和nginx来做反向代理,windows上可以用IIS进行反向代理. 反向代理可以提供很多特性,固然很好.但是 ...

  7. BugkuCTF web3

    前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...

  8. python基础知识小结-运维笔记

    接触python已有一段时间了,下面针对python基础知识的使用做一完整梳理:1)避免‘\n’等特殊字符的两种方式: a)利用转义字符‘\’ b)利用原始字符‘r’ print r'c:\now' ...

  9. Daily scrum 12.24

    平安夜闲得想来一遍scrum,添加了之前ui组的数据库问题修复任务. 其实是之前忘记在任务中添加了.现在基本修复完成. Member Today’s task 林豪森 与学霸其他小组交流,处理整合问题 ...

  10. Scrum Meeting NO.7

    Scrum Meeting No.7 1.会议内容 经过老师提醒,我们认识到,应尽快把主要功能实现,其他的细枝末节应在这之后慢慢添加.当今最重要的任务是和online组和数据处理组实现数据共享. 此外 ...