一,引言

现在我有个问题,函数里面的变量,在函数外面能直接引用么?

def func1():
m = 1
print(m)

print(m) #这行报的错

报错了:
NameError: name 'm' is not defined

上面为什么会报错呢 ?现在我们来分析一下python内部的原理是怎么样:

  我们回忆一下python代码的运行是哦湖遇到函数是怎么做的,从python解释器开始执行后,就在内存开辟一个空间,每当遇到一个变量的时候,就把变量名和值之间的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读到内存。表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。

  

等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。

代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;

在函数的运行中开辟的临时的空间叫做局部命名空间。

二,命名空间和作用域

>>> import this
The Zen of Python, by Tim Peters Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those! python之禅 python之禅

在python之禅中到过:命名空间是一种绝妙的理念,让我们尽情的使用发挥吧!

命名空间一共分为三种:

  全局命名空间

  局部命名空间

  内置命名空间

内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

三种命名空间之间的加载与取值顺序:

加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

取值顺序:

  在局部调用:局部命名空间->全局命名空间->内置命名空间

  在全局调用:全局命名空间->内置命名空间

综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。

作用域

作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

局部作用域:局部名称空间,只能在局部范围生效

#*args 动态参数,万能参数
#args接受的就是实参对应的 所有位置参数,并将其放在元组中。

def func(*args):
print(args)
print(func(1,2,3,4,5,7,8,9,1,2,3,4,5,6,7,8))

#形参对应顺序:
#位置参数,*args,默认参数

执行后输出:

1
2
3
4
(5, 6, 7)

#**kwargs 动态传参,他将所有的关键字参数(无异议)的放到一个字典中
def func(a,b,c,**kwargs):
print(kwargs)
func(1,2,r=4,b1=5,c1=6,c=7)

  执行后输出:

# # * 魔法运用
def func(*args):
print(args) #(1,2,30,1,2,33.。。。。。)
l1 = [1,2,30]
l2= [1,2,33,21,45,66]
func(*l1,*l2) #在函数的调用时,*代表打散

  执行后输出:

###

**kwargs
def func(**kwargs):
print(kwargs) dic1 = {'name1':'alex','age1':46}
dic2 = {'name':'hobby','age':56}
func(**dic1,**dic2)

输出后的结果:

说明:

1.  在函数的调用执行时,
2.  *可迭代对象,代表打散(list,tuple,str,dict(键))将元素一一添加到args。
3. **字典,代表打散,将所有键值对放到一个kwargs字典里。

在函数定义时, *args,**kwargs代表的是聚合。  

def func(*args,**kwargs):
print(args)
print(kwargs)
dic1 = {'name1':'alex','age1':46}
dic2 = {'name':'hobby','age':56}
func(*[1,2,3,4],*'asdfses',**dic1,**dic2)

 执行后输出:

 函数--名称空间,临时名称空间

a = 4
b = 3
c = [1,2,3,4]
c1 = {'name':'alex'} def func1():
name = 'hobby'
print(name)
func1()

  执行后输出:

当执行函数的时候,他会在内存中开辟一个临时名称空间,存放函数体内的所有变量与值的关系。

随着函数的执行完毕,临时空间自动关闭。

name = 'python'
def func1():
name = 'jack'
print(name)
func1()

  执行后输出:

def func1():
name = 'joanna'
print(name)
func1()

  执行后输出:

函数什么时候执行? 函数调用的时候执行。
# 代码从上至下依次执行, 调用函数:函数里面从上至下依次执行。

print(111)
def func1():
print(333) def func2():
print(444) def func3():
print(555)
func2()
func1()
print(222)

  执行后输出:

print(111)
def func1():
print(333)
func2()
print(666) def func2():
print(444) def func3():
print(555) func1()
print(222)

  执行后输出:

全局变量

a = 2
b = 3
def func1():
c = 5
d = 6
print(globals()) # 全局变量放在一个字典中
return locals() # {'c': 5, 'd': 6}
print(func1())

执行输出:

关键字:global,nonlocal

# print(globals()) # 全局名称空间:所有变量
# print(locals()) # 局部名称空间:所有变量

#global
# 1,在局部空间内,声明一个全局变量

def func1():
global name
name = 'hobby'
print(name)
func1()
print(func1())

 执行后输出:

2,在局部空间内改变一个全局变量

a = 4
def func1():
global a
a = 5
func1()
print(a)

  执行后:

#nonlocal
# 1,不能修改全局变量。

a = 4
def func1():
nonlocal a
a = 5
# print(name)
func1()
print(a)

 执行后输出:

 

重点注意:

#在局部作用域中,对父级作用域(或者更外层作用域但非全局作用域)的变量进行引用和修改,
# 并且引用的哪层,就从那层及以下此变量全部发生改变。

  

python全栈学习--day10(函数进阶)的更多相关文章

  1. python全栈开发-前方高能-函数进阶

    python_day_10 一.今日主要内容 1. 动态参数 位置参数的动态参数: *args 关键字参数的动态参数 : **kwargs 顺序: 位置,*args,默认值,**kwargs 在形参上 ...

  2. python全栈学习--day11(函数高级应用)

    一,函数名是什么? 函数名是函数的名字,本质:变量,特殊的变量. 函数名()执行此函数 ''' 在函数的执行(调用)时:打散. *可迭代对象(str,tuple,list,dict(key))每一个元 ...

  3. python全栈学习--day9(函数初始)

    Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也 ...

  4. Python全栈之路----函数进阶----名称空间

    又名name space,顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的=地方 名称空间共3种,分别如下 ...

  5. Python全栈之路----函数进阶----装饰器

    Python之路,Day4 - Python基础4 (new版) 装饰器 user_status = False #用户登录后改为True def login(func): #传入想调用的函数名 de ...

  6. Python全栈之路----函数进阶----迭代器

    我们已经知道,可以直接作用于 for 循环的数据类型有以下几种: 一类是集合数据类型,如 list , tuple , dict , set ,str 等: 一类是 generator ,包括生成器和 ...

  7. Python全栈之路----函数进阶----作用域的查找空间

    n = 10 def func(): n = 20 print('func:',n) def func2(): n = 30 print('func2:',n) def func3(): print( ...

  8. Python全栈之路----函数进阶----闭包

    关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个这样的内部函数在包含它们之外被调用时,就会形成闭 ...

  9. Python全栈之路----函数进阶----生成器

    生成器特点: 不能立即产生,取一次创建一次 只能往前走 等到走到最后,就会报错 >>> a = [i for i in range(1000)] >>> a [0, ...

随机推荐

  1. OpenStack_I版 2.keystone部署

    生成keystone默认证书,指定用户 修改keystone主配置文件 第625行,修改数据库连接方式   修改完成同步数据库 同步完成可以查看数据库是否有表生成 为了以后调试keystone方便,现 ...

  2. tar、scp、sftp、rsync简单使用

    tar -c 创建一个归档文件 -z 指定压缩格式为gzip -v 显示详细信息 -f 制定文件明 -j 指定压缩格式为bz2 -J 指定压缩格式为 xz -C 压缩.解压至某个目录 -x 自动识别压 ...

  3. Ajax前后台交互函数

    function AJAX(obj){ //做网络请求的时候参数以对象的形式传递进来 //我们规定obj里面包含属性:url, //请求方式type, //date前端给后端传递的参数 //回调函数s ...

  4. hdu5977 Garden of Eden

    都不好意思写题解了 跑了4000多ms 纪念下自己A的第二题 (我还有一道freetour II wa20多发没A...呜呜呜 #include<bits/stdc++.h> using ...

  5. MFC与Webbrower交互(通过JS)

    最近修改老旧的MFC项目,用的网页做界面,和HTML交互采用的是COM方式,繁琐,丑陋又性能低,于是考虑利用js来进行界面交互,查了一天的资料,现在整理如下,供后来需要的人参考,虽然大概几乎不会有人用 ...

  6. 【原】storm组件(架构层面)

    Strom集群遵循从主模式,主与从之间通过Zookeeper协作.架构层面上包括三个组件: 1) Nimbus Node 2)Supervisor Nodes 3)Zookeeper 其中Nimbus ...

  7. springboot入门的一点基础

    什么是SpringBoot java问世20年由于,发展到现在从技术角度来说已经很成熟,开发过程中我们总是在想如何去提高团队开发规范性.减少重复配置.避免低效开发.部署发布时流程的复杂度以及第三方技术 ...

  8. 【BZOJ2186】沙拉公主的困惑(数论)

    [BZOJ2186]沙拉公主的困惑(数论) 题面 BZOJ 题解 考虑答案是啥 先假设\(n=m\) 现在求的就是\(\varphi(m!)\) 但是现在\(n!\)是\(m!\)的若干倍 我们知道 ...

  9. 最长k可重线段集问题

    和那道可重区间集一样 不过这道题可能有垂直于x轴的线段,这就很烦了,直接连会有负环,判掉又会WA 可以想办法把r端点和l端点分开,又要保证答案不变 那么直接把区间l,r都乘以2,l=r时r++,否则l ...

  10. 用vmware workstation制作cloudstack(kvm)镜像及问题解决办法

    说明1:vmware workstation镜像是vmdk格式 说明2:cloudstack配置文件目录:/run/libvirt/qemu/     kvm配置文件目录:/etc/libvirt/q ...