一、参数陷阱

在使用默认参数时,可能碰见下列情况
def show_args_trap(i, li = []):
li.append(100)
li[i] = 101
print(li)
show_args_trap(0)
show_args_trap(1)
show_args_trap(2)
# 显示结果为:
# [101]
# [101, 101]
# [101, 101, 101]

分析:
  大家知道:含有默认参数的,不输入该参数就使用默认的值;
在这里,第一次调用函数的时候,只传入一个参数0,这时默认参数起作用,li=[];
接着给这个列表尾部加入元素100, li = [100];
继续修改该列表,将第一元素替换成101,所以li=[101

  我们接着分析第二次调用:传入参数1,此时内存中已经有了li = [101],所以默认参数没起作用! ***此处就是陷阱所在,按照默认参数的使用规则,li此时应该为空的
列表追加元素100,所以 li = [101,100];
列表修改,li = [101,101];
.........

总结:如果默认参数的值是一个可变的数据类型,那么每一次调用函数的时候,如果不传值,就公用这个数据类型的资源!

二、函数的命名空间和作用域

1、命名空间的引入

a = 1
def func():
print(a)
func()

  每个名字都有其作用的范围,变量名a,可以在函数定义中使用,这说明a在一定的空间内!而且有其作用的范围!

2、命名空间的分类

  1)、内置命名空间 --- python解释器
     就是python解释器以启动就可以使用的名字,它存储在内置命令空间里;
    内置的名字在启动python解释器的时候就被加载到内存中了!
  2)、全局命名空间 -- 写的代码,但不是函数中的代码
    是在代码从上到下被执行的过程中,依次加入到内存中的,
    它放置了我们设置的所有变量名和函数名!
  3)、局部命名空间 -- 对应函数中的定义的名称
    就是函数内部定义的名字;
    当调用的时候,才会产生这个命名空间,随着函数的执行结束而结束,这个命名空间就消失了!''

 #   作用域及其分类
''' 全局作用域 -- 作用在全局 -- 内置和全局命名空间中的名字都属于全局作用域 -- 可使用globals()
局部作用域 -- 作用在局部 -- 基本在函数内部(局部命名空间中的名字属于局部作用域) -- 可使用locals()'''
a_b = 1
def self_func():
#a_b += 2 # 报错:局部作用域中,不能修改全局作用域中的变量
global a_b # 加关键字后即可,但是不推荐经常使用,特殊情况下用!
a_b += 2
return a_b
self_func()

3、名字的使用范围:
  1)、在局部命名空间:可以使用内置命名空间中的名字,也可以使用全局命名空间中的名字;
  2)、在全局命名空间:可以使用内置。
  3)、在内置命名空间:不能使用全局和局部命令空间中的名字,只能使用自己内部的名字。

 b = 101
def func_inner():
c = b + 100 # 会划出内置命名空间,存储c,它用到了全局命名空间中的名字b
return c
print(func_inner()) # 这里print是内置命名空间中的名字 def print():
return '局部命名空间中的名字print,与内置命名空间的名字print一样'
print() # 在全局命名空间中,无法使用内置的命名空间中的名字,只能使用自己的和内置的!自己有,就不用调用内置的print函数

4、特殊使用范例:

def max(list):
print('in max func')
print(max([1,2,3]))

说明:

  • 在正常情况下,直接使用内置的名字
  • 当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
  • 当我自己有的时候 我就不找我的上级要了
  • 如果自己没有 就找上一级要 上一级没有再找上一级 如果内置的名字空间都没有 就报错
  • 多个函数应该拥有多个独立的局部名字空间,不互相共享
#   在 “函数名()”中,函数名就是函数在内存中的地址,加()就是说要调用该函数了!
print(min) # <function max at 0x000002A08BCDE620>
print(min('ab11238'))

5、globals()与locals()的使用

# 对于不可变数据类型 在局部可是查看全局作用域中的变量
# 但是不能直接修改
# 如果想要修改,需要在程序的一开始添加global声明
# 如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
 a = 1
b = 2
def func():
x = 'aaa'
y = 'bbb'
print(locals()) # 输出什么 根据locals所在的位置 --如今在局部中,所有输出的是局部的名称
print(globals()) # 永远打印全局的名字 func()
print(globals())
print(locals()) #本地的 现在全局中,所以打印的和globals()的结果一样!

三、嵌套和作用域

1、函数的嵌套的示范

def max(a, b):
return a if a > b else b def max(x, y, z):
c = max(x, y)
return max(c, z)

2、函数的嵌套定义:
函数中定义另外一个函数,内部函数可以使用外部函数的变量

 a = 1 # 全局变量
def outer():
a = 1
def inner():
b = 2
# global a
nonlocal a # 声明了一个离它最近的局部变量,对全局无效
a += 1 #不可变数据类型的修改,不在一个作用域内,是非法的;需要声明nonlocal,不建议使用global
print(a) # 一个局部包含另外一个局部
print('inner space')
def inner2(): # 没有调用,就没输出,所有的函数都是先定义后调用
print(a, b)
print('inner 2 layer')
inner2()
print('局部第二层:',a)
inner() # 只有在才可以调用
print('局部第一层:', a)
outer()
print('全局',a) # 总结:nonlocal关键字,声明的变量仅仅对离它最近一层的局部变量有效,不管是不是在一个局部域内! # 函数名可以赋值
def func(): # 函数名就是内存地址
print('wo men')
func2 = func # 函数名可以赋值
func2() list = [func, func2] # 函数名可以作为容器类型的元素
for i in list:
print(123) # 函数名可以作为函数的参数
def arg_fun(f):
f()
return f arg_fun(func2) # 函数名可以作为函数的返回值
def fun_as_return(f):
return f fun_as_return(func2)() # 第一类对象
# 1、可以在运行期创建;
# 2、可用作参数
# 3、可存入变量的实体

四、闭包

1、定义:就是嵌套函数中,内部函数调用外部函数的变量

 def outer():
a = 1
def inner():
print(a)
print(inner.__closure__) # 结果:(<cell at 0x0000019EE0F37CA8: int object at 0x00000000763D5320>,)
outer()
print(outer.__closure__) # (<cell at 0x000002A5A6CC7CA8: int object at 0x00000000763D5320>,) None # 运用闭包的常见的方式
def outer1():
a = 1
def inner():
print(a)
return inner
inn = outer1()
inn()

2、闭包的应用 爬虫初步

 #   import urllib   #python自带的模块,
from urllib.request import urlopen
#
# # todo 改造下面的函数get_url()为闭包模式,不用每次调用的时候,频繁打开和关闭url变量,占用资源
# def get_url():
# url = 'https://www.baidu.com/?tn=80035161_1_dg'
# result = urlopen(url).read()
# print(result)
# get_url() def get_url():
url = 'https://www.baidu.com/?tn=80035161_1_dg'
def get_url_inner():
res = urlopen(url).read()
print(res)
return get_url_inner # 与def 平级,否者报错,TypeError: 'NoneType' object is not callable
get = get_url()
get()

Python进阶-II 参数陷阱、命名空间、嵌套、作用域、闭包的更多相关文章

  1. day11函数的进阶动态参数,命名空间,作用域,第一类对象

    一.习题收藏 5.写函数,计算传入字符串中[数字].[字母].[空格] 以及 [其他]的个数,并返回结果. # def func4(s): # dic = { # 'num':0,'alpha':0, ...

  2. 【转】Python函数默认参数陷阱

    [转]Python函数默认参数陷阱 阅读目录 可变对象与不可变对象 函数默认参数陷阱 默认参数原理 避免 修饰器方法 扩展 参考 请看如下一段程序: def extend_list(v, li=[]) ...

  3. 自学python day 10 函数的动态参数、命名空间、作用域

    作业提升: s为字符串 s.isalnum() 所有字符都是字母或者数字 s.isalpha() 所有字符都是字母 s.isdigit() 所有字符否是数字 2. for i in range(1,1 ...

  4. 吴裕雄--天生自然python学习笔记:Python3 命名空间和作用域

    命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的. 命名空间提供了在项目中避免名字冲突的一种方法.各个命名空间是独立的,没有任何关系的,所以一个 ...

  5. 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

    一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...

  6. Python面试题目之Python函数默认参数陷阱

    请看如下一段程序: def extend_list(v, li=[]): li.append(v) return li list1 = extend_list(10) list2 = extend_l ...

  7. python day- 10 动态参数 函数的嵌套 命名空间和作用域 global和nolocal

    一.动态参数: 动态参数是形参的一类 分为:动态位置参数(* + 函数名)表示 调用后返回的是元祖 动态关键字参数(** + 函数名)表示 形参的排列顺序: 位置参数     >   动态位置参 ...

  8. python函数默认参数陷阱

    对于学习python的人都有这样的困惑 def foo(a=[]): a.append(5) return a Python新手希望这个函数总是返回一个只包含一个元素的列表:[5].结果却非常不同,而 ...

  9. python 嵌套作用域 闭包函数

    #闭包函数 def multiplier(factor): def multiplyByFactory(number): return number*factor return multiplyByF ...

随机推荐

  1. [转载]3.11 UiPath存在文本Text Exists的介绍和使用

    一.Text Exists的介绍 检查是否在给定的UI元素中找到了文本,输出的是一个布尔值 二.Text Exists在UiPath中的使用 1.打开设计器,在设计库中新建一个Sequence,为序列 ...

  2. C# HTTP系列7 HttpWebRequest.Method属性

    系列目录     [已更新最新开发文章,点击查看详细] HttpWebRequest.Method属性,获取或设置请求的方法.用于联系 Internet 资源的请求方法. 默认值为 GET. Syst ...

  3. Scala 定义复杂枚举

    通常我们需要枚举参数不止两个,Scala提供的枚举类最多定义两个参数:id:Int与name:String.不能满足我们通常要求. object BaseEntryEnum extends Enume ...

  4. 【08月07日】A股滚动市盈率PE最低排名

    ​仅根据最新的市盈率计算公式进行排名,无法对未来的业绩做出预测. 方大集团(SZ000055) - 滚动市盈率PE:2.32 - 滚动市净率PB:1.04 - 滚动年化股息收益率:4.37% - 建筑 ...

  5. Qt 绘制图表 - Qt Charts版

    一.前言 自从 Qt 发布以来,给广大跨平台界面研发人员带来了无数的福利.但是Qt自己却一直没有提供自带的图表库,这就使得 QWT.QCustomPlot 等第三方图表库有了巨大的生存空间,为了降低开 ...

  6. Kettle提高表输出写入速度(每秒万条记录)

    重点: ETL 优化多数在于表输入和表输出. 转自: https://blog.csdn.net/qq_37124304 https://blog.csdn.net/qq_37124304/artic ...

  7. Angular中上传图片到分布式文件服务器FastDFS上

    使用步骤 1.上传下载需要的依赖 2.springmvc中配置多媒体解析器并加载 <!-- 配置多媒体解析器 --> <bean id="multipartResolver ...

  8. Mysql load data infile 命令导入含中文csv源数据文件 【错误代码 1300】

    [1]Load data infile 命令导入含中文csv源数据文件 报错:Invalid utf8 character string: '??֧' (1)问题现象 csv格式文件源数据: 导入SQ ...

  9. python调用MySQL数据库

    在Python中访问mysql数据库中的数据需要三步骤: 1,建立连接 2,操作数据库 3,连接关闭

  10. 使用 Docker 和 Jenkins 持续交付(新书免费获取!)

    今天没有长篇大论,给大家推荐一本新书,书名:Continuous Delivery with Docker and Jenkins.封面如图所示: 以下内容纯属凑字数 本书结合了 Jenkins 和 ...