通过5个知识点轻松搞定Python的作用域

来源:本网整理

1.这个怎么看,我不能理解;2.全局变量局部变量有什么区别吗? 区别肯定有的,不然名字就没必要区分了

s">

通过5个知识点轻松搞定Python的作用域

投稿:daisy 字体:[增加 减小] 类型:转载 时间:2016-09-09 我要评论 网上关于python的作用域介绍有很多,那么小编今天给大家分享的这篇文章是让大家通过学习这5个知识点,可以轻松搞定Python的作用域,有需要的朋友们可以参考借鉴。 ">

1、块级作用域

简单说,闭包就是根据不同的配置信息得到不同的结果再来看看专业的解释:闭包(Closure)是

想想此时运行下面的程序会有输出吗?执行会成功吗?

Python学得倒不用很深,循环跟函数还有类学完就可以搞深度学习了。 新手用深度学习库先跑跑,真要进

#块级作用域 if 1 == 1: name = "lzl" print(name) for i in range(10): age = i print(age)

你可以 在 B页面 里面直接 调用 一下 函数 运行一下 ,你可以发现应该和 刚才 执行A 页面

我们先看下执行结果

谢邀,众泰车是目前比较大的一个国产车品牌,外观和汽车内饰都是非常突出,一直都是以模仿、借鉴出名1、众泰z700排量为1.8L,对于一般驾驶者来说已经足够,它的内饰和奥迪A6相似程度高达百分之70以上。汽车配置非常丰富,从电吸门到伸缩液晶屏应有尽有。长为5020mm,宽为1877mm,高位1469mm,所以车子的内饰非常不错,并且从外观来讲众泰的车身造型是数一数二的,目前来说十多万就能买一台这样的车的确非常划算,按照合资车来算它的这些配置,没有50万基本是下不来的。但是众泰的发动机和车身细节一直被很多车主吐槽,发动机是TN4G18T型号的,油耗偏高动力输出不错,但众泰车主说经常出现小部件零件损坏

C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py lzl 9 Process finished with exit code 0

【事件回顾】2008年9月,三鹿生产的婴儿奶粉,被发现导致多位食用婴儿出现肾结石症状,“三聚氰胺”事件爆发。据卫生部通报,截止2008年12月底,全国累计报告因食用三鹿牌奶粉和其他个别问题奶粉导致泌尿系统出现异常的患儿共29.6万人。三鹿毒奶粉事件迅速扩大,越来越多患有肾结石的婴儿被发现,广东也陆续收治相关病例。而在事件被最早曝光的甘肃,已出现与三鹿奶粉密切联系的死亡报告。前日,三鹿公司先是矢口否认,但很快就改变说法,承认奶粉受到污染。三鹿公司给出调查结果,所谓污染是由奶农在原奶中掺加三聚氰胺造成,石家庄还据此传唤了嫌疑人员。事态目前在国内继续蔓延,这场危机闹得沸沸扬扬。对三鹿公司来说,眼下所

代码执行成功,没有问题;在Java/C#中,执行上面的代码会提示name,age没有定义,而在Python中可以执行成功,这是因为在Python中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功;  

民谚有云:“家有三宝:丑妻热炕破棉袄”,意指三者同样具备实而不华的特质,诸葛亮与丑妻黄月英的美满爱情,更被视为佳话。李维嘉的老婆其实是素有“快女教母”的龙丹妮,背景雄厚,两人生活相当甜蜜,李维嘉的老婆对他的事业也起到了很重要的作用。网友们说小沈阳的妻子是翻版的郭德纲,可是都不影响到两口子之间的恩爱。小沈阳甚至向沈春阳公开示爱:“这半辈子欠你太多,就这样牵手下去!永远爱你!”有人说黄渤的妻子比黄渤还黄渤。但是黄渤却对妻子恩爱有加。黄渤说:有没有永久的爱情我不知道,我只知道有永久的感情,到最后就是亲情,这才是最可靠的情感。梁家辉与曾是香港电台制作人的江嘉年,两人一见钟情。生了孩子的江嘉年身材开始走

 2、局部作用域

催乳师,是对专门催乳的人员的一种称呼,催乳师就是通过催乳技术即中医推拿手法,为产妇解决产后无乳、乳少等症状的专业护理人员。催乳师有没有效,要看催乳的手法专业不专业。第一次当妈,觉得”母乳喂养“是水到渠成的事,所以产前没有对这方面做充分的了解。生了孩子之后,才知道”母乳喂养“这个问题,不亚于”产后抑郁“,或者说,是”产后抑郁“的催化剂。多少新妈妈因为”首次当妈“内心充满困惑和焦虑,当孩子永不休止地吃奶时,当孩子吃吃睡睡时,当孩子不断啼哭时,周围充斥着各种声音——“孩子是不是饿了?“”是不是不够奶吃“,“肯定是不够奶,所以饿醒了!“这个时候,原本并不肯定的新妈妈就会更加焦虑,于是火速求救,请来了”

回顾之前学过的知识,我们学函数的时候,函数是个单独的作用域,Python中没有块级作用域,但是有局部作用域;看看下面的代码

#局部作用域 def func(): name = "lzl" print(name)

运行这段代码,想想会不会有输出?

Traceback (most recent call last): File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py", line 23, in <module> print(name) NameError: name 'name' is not defined

运行报错,我相信这个大家都能理解,name变量只在func()函数内部中生效,所以在全局中是没法调用的;对上面代码做个简单调整,再看看结果如何?

#局部作用域 def func(): name = "lzl" func() #执行函数 print(name)

对之前的代码添加了一句代码,在变量name打印之前,执行了一下函数,此时打印会不会有变化?

Traceback (most recent call last): File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py", line 23, in <module> print(name) NameError: name 'name' is not defined

执行依然报错,还是回到刚才那句话:即使执行了一下函数,name的作用域也只是在函数内部,外部依然无法进行调用;把前两个知识点记住,接下来要开始放大招了

3、作用域链

对函数做下调整,看看下面的代码执行结果如何?

#作用域链 name = "lzl" def f1(): name = "Eric" def f2(): name = "Snor" print(name) f2() f1()

学过函数,肯定知道最后f1()执行完会输出Snor;我们先记住一个概念,Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错

4、终极版作用域

好,铺垫了够了,终极版的来了~~

#终极版作用域 name = "lzl" def f1(): print(name) def f2(): name = "eric" f1() f2()

想想最后f2()执行结果是打印“lzl”呢,还是打印“eric”?记住自己的答案,现在先不把答案贴出来,先看看下面这段代码:

#终极版作用域 name = "lzl" def f1(): print(name) def f2(): name = "eric" return f1 ret = f2() ret() #输出:lzl

执行结果为“lzl”,分析下上面的代码,f2()执行结果为函数f1的内存地址,即ret=f1;执行ret()等同于执行f1() ,执行f1()时与f2()没有任何关系,name=“lzl”f1()在一个作用域链,函数内部没有变量是会向外找,所以此时变量name值为“lzl”;理解了这个,那么刚才没给出答案的那个终极代码你也知道答案了

#终极版作用域 name = "lzl" def f1(): print(name) def f2(): name = "eric" f1() f2() # 输出:lzl

是的,输出的是“lzl”,记住在函数未执行之前,作用域已经形成了,作用域链也生成了

5、新浪面试题

li = [lambda :x for x in range(10)]

判断下li的类型?li里面的元素为什么类型?

print(type(li)) print(type(li[0])) # <class 'list'> # <class 'function'>

可以看到li为列表类型,list里面的元素为函数,那么打印list里面第一个元素的返回值,此时返回值为多少?

#lambada 面试题 li = [lambda :x for x in range(10)] res = li[0]() print(res) #输出:9

li第一个函数的返回值为9还不是0,记住:函数在没有执行前,内部代码不执行;博客里面的代码可以自己练练,加深下印象

总结

以上就是这篇文章的全部内容了,不知道对大家的学习和工作能不能带来一些帮助,如果大家有疑问可以留言交流。

扩展阅读,根据您访问的内容系统为您准备了以下内容,希望对您有帮助。

PYTHON 的变量作用域与内存分配

原理:python中任何变量都是对象,所以参数只支持引用传递方式。即通过名字绑定的机制,把实际参数的值和形式参数的名称绑定在一起,形式参数和实际参数指向内存中的同一个存储空间。

回答问题2:

每一次给变量赋值就是把这个名称的值在一个新内存中存储 你print (id (a)) 会发现每一次f(x),a的内存地址都是新的。所以你的问题二中L=[4,3] 与之前的L[]不是同一个名称,所以append上a就是[4,3,3](简明点就是L=[4,3]与L=[1,2]是两不同名的玩意)

讨论问题1:

在你的程序中a=1,a=2,a=5是int对象的三个实例,所以占用的是三段不同的内存,自然在程序执行完收回内存的时候才会被清理;而L是通过列表的append方法进行变化时,print (f(1))

print (f(2)) print (f(5))是对对一个实例进行操作的,所以内存地址不变; 同理print (f(3,[4,3]))直接给L赋值时,由于 是一个新的列表实例了,内存位置自然变化。

产生以上的问题的根本原因就是python的精髓:万物皆对象 (赋值的过程是对象的实例化)

看完自己的回答后:感觉真的很绕,不过我是尽力了,希望你能看懂,不明白的话,在追问里注明吧!追问十分感谢,但是我还有些问题。

如果a和L是在main的生命周期结束后才销毁,那在main中重复调用f(),f(1,[1]),f(2,[2]),f(3,[3]).....这样搞个几万次,那每次都会有新的实例生成并且只在程序结束时回收?这样不是会造成泄漏?是否需要在f()函数最后del(a)呢?

还有,我那段代码起初是在python3x上跑的,4次ID的地址一样,所以我很奇怪。

今天拿到2x上跑,第三次就不一样了,这样还比较好理解。第三次肯定是申请了新内存。追答好吧,承认这个问题问的很好,我也受教了。以下是我查到的资料。应该可以解决你的疑惑了。呵呵

小块空间的内存池

  在Python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。

 Python内存池全景

  这就意味着Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。这也就是之前提到的Pymalloc机制。

  在Python 2.5中,Python内部默认的小块内存与大块内存的分界点定在256个字节,这个分界点由前面我们看到的名为SMALL_REQUEST_THRESHOLD的符号控制。

  也就是说,当申请的内存小于256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python的默认内存管理行为。

  在一个对象的引用计数减为0时,与该对象对应的析构函数就会被调用。

  Python内存管理规则:del的时候,把list的元素释放掉,把管理元素的大对象回收到py对象缓冲池里。

---------------

以上不是完整的,字数受限,详细请看

http://www.techweb.com.cn/tech/2010-07-23/647118.shtml

python中实例属性和类属性之间的关系

一般来说,在Python中,类实例属性的访问规则算是比较直观的。

但是,仍然存在一些不是很直观的地方,特别是对C++和Java程序员来说,更是如此。

在这里,我们需要明白以下几个地方:

1.Python是一门动态语言,任何实体都可以动态地添加或删除属性。

2.一个类定义了一个作用域。

3.类实例也引入了一个作用域,这与相应类定义的作用域不同。

4.在类实例中查找属性的时候,首先在实例自己的作用域中查找,如果没有找到,则再在类定义的作用域中查找。

5.在对类实例属性进行赋值的时候,实际上会在类实例定义的作用域中添加一个属性(如果还不存在的话),并不会影响到相应类中定义的同名属性。

下面看一个例子,加深对上述几点的理解:

复制代码

代码如下:

class A:

cls_i = 0

cls_j

= {}

def __init__(self):

self.instance_i =

0

self.instance_j =

{}

在这里,我们先定义类A的一个实例a,然后再看看类A的作用域和实例a的作用域中分别有什么:

复制代码

代码如下:

>>> a = A()

>>>

a.__dict__

{'instance_j': {}, 'instance_i': 0}

>>>

A.__dict__

{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {},

'__doc__': None}

我们看到,a的作用域中有instance_i和instance_j,A的作用域中有cls_i和cls_j。

我们再来看看名字查找是如何发生的:

复制代码

代码如下:

>>> a.cls_i

0

>>>

a.instance_i

0

在查找cls_i的时候,实例a的作用域中是没有它的,却在A的作用域中找到了它;在查找instance_i的时候,直接可在a的作用域中找到它。

如果我们企图通过实例a来修改cls_i的值,那会怎样呢:

复制代码

代码如下:

>>> a.cls_i = 1

>>>

a.__dict__

{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}

>>>

A.__dict__

{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {},

'__doc__': None}

我们可以看到,a的作用域中多了一个cls_i属性,其值为1;同时,我们也注意到A作用域中的cls_i属性的值仍然为0;在这里,我们其实是增加了一个实例属性,并没有修改到类属性。

如果我们通过实例a操纵cls_j中的数据(注意不是cls_j本身),又会怎么样呢:

复制代码

代码如下:

>>> a.cls_j['a'] =

'a'

>>> a.__dict__

{'instance_j': {}, 'cls_i': 1, 'instance_i':

0}

>>> A.__dict__

{'__init__': , '__module__': '__main__',

'cls_i': 0, 'cls_j': {'a': 'a'}, '__doc__': None}

我们可以看到a的作用域没有发生什么变化,但是A的作用域发生了一些变化,cls_j中的数据发生了变化。

实例的作用域发生变化,并不会影响到该类的其它实例,但是类的作用域发生变化,则会影响到该类的所有实例,包括在这之前创建的实例:

复制代码

代码如下:

>>> A.cls_k = 0

python 函数作用域问题,

类在定义的时候是有作用域的,这个作用域内的变量只能在 class 块内访问,而不能在类的方法(函数)中访问。

python global的作用域

golbal s 指定当前作用域里面的s是全局的,不影响其他的作用域

  • 本文相关:
  • Python冒泡排序注意要点实例详解
  • Python 中的with关键字使用详解
  • Python优化技巧之利用ctypes提高执行速度
  • Python 如何访问外围作用域中的变量
  • Python中使用asyncio 封装文件读写
  • asyncio 的 coroutine对象 与 Future对象使用指南
  • 基于asyncio 异步协程框架实现收集B站直播弹幕
  • python开发环境PyScripter中文乱码问题解决方案
  • Python读取图片属性信息的实现方法
  • 全面了解python中的类,对象,方法,属性
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved