Python学习 day10
一、默认参数的陷阱
先看如下例子:
def func(li=[]):
li.append(1)
print(li) func()
func()
func(li=['abc'])
func()
结果:
可以看到,默认参数不传值使用默认值时,多次调用函数li始终使用同一个列表。
如果默认参数是一个可变数据类型,每一次调用函数时,不传值就公用这个数据类型的资源。
使用pycharm写代码的时候,若在函数定义时将可变数据类型用作默认参数,pycharm会给出提示:
Default argument value is mutable
Inspection info: This inspection detects when a mutable value as list or dictionary is detected in a default value for an argument. Default argument values are evaluated only once at function definition time, which means that modifying the default value of the argument will affect all subsequent calls of the function.
二、三元运算符
变量 = 条件返回True的结果 if 条件 else 条件返回False的结果,例:
# 定义一个求两数中较大值的函数
def max(a, b):
return a if a > b else b print(max(12, 7))
print(max(3, 5))
系统中内置函数里也有max()函数,求取得是所有参数中的最大值,也可以传入iterable对象
三、命名空间
内置命名空间
就是python解释器一启动就可以使用的名字存储在内置命名空间中
内置的名字在启动解释器的时候被加载进内存里
全局命名空间
是在程序从上到下被执行的过程中依次加载进内存的
放置了我们设置的所有变量名和函数名
局部命名空间
就是函数内部定义的名字
当调用函数的时候才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了
在python解释器下输入import this,可以看到:
>>> 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!
>>>
最后一句:
Namespaces are one honking great idea -- let's do more of those!
阐明了命名空间的重要性
四、变量作用域
变量的作用域在每种语言都是一个需要注意的问题,python也一样,python中变量的作用域依赖于命名空间,自己知道的js有命名空间,其他语言就不清楚了。
- 在局部:可以使用全局、内置命名空间的名字
- 在全局:可以使用内置命名空间中的名字,但是不能用局部中的名字
- 在内置:不能使用局部和全局的名字
在之前学习的可直接调用的方法、关键字都是存在于内置命名空间的,如print(),input(),del,def,for...in...等,所以我们可以直接调用
另外,对于已有定义的函数,都可以在能够使用它的命名空间里对它进行覆写,例:
def max(*args):
print('max1') def max(*args):
print('max2') max(1, 3)
结果:
如上,在全局命名空间里我们定义了两次max()函数,最终max(1, 3)调用的方法是最后一个max(),即每次定义都对原有名字进行了覆盖。
可以说,遵循的就是一个就近原则
作用域:
- 全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域 —— globals()查看
- 局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域)—— locals()查看
综上,因为依赖倒置的关系,内部的命名空间可以使用外部的命名空间中的变量,反之不行,即有:
a = 1 def func():
print(a) func()
func()是可以正常获取a的值并打印的,但是,能获取使用并不代表可以修改,如下:
a = 1 def func():
a = 2
print(a) func()
print(a)
结果:
可以看到,函数内部虽然a的值为2,但对于全局命名空间中的a,值依然是1,说明在func()内部并没有修改变量a的值。
但目前存在我们需要对外部变量修改的情况,在python中也是提供了解决方法的:
a = 1 # 全局中是否有变量a都一样 def func():
global a # 声明全局变量a
a = 2
print(a) func()
print(a)
结果:
可以看到,在函数内部将变量a声明为global后,a即为全局变量,全局作用域中有无a都一样,在函数内部的修改也会对全局作用域中的a进行修改。
注意:以上只针对不可变数据类型适用
在局部作用域虽然不能直接修改全局作用域中不可变数据类型的值,但是对可变的数据类型,是可以进行修改的,如下:
a = [1, 2] def func():
a.append(1)
print(a) func()
print(a)
结果:
可以看到,对于可变数据类型,在函数内部是可以对全局作用域中的变量进行修改的。
总结:
1、对于不可变数据类型,在局部可以查看全局作用域中的变量,但是不能直接修改;
2、如果想要修改,需要在函数的一开始添加global声明;
3、如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效。
globals() -- 得到所有的全局变量
locals() -- 得到所有的本地变量 -- 意思是在函数内获取即得到本函数的作用域下的变量,在全局获取得到的与globals()结果相同,也是全局变量
五、函数的嵌套调用
即函数之间可以互相调用,只要是能获取的名字都可以,如:
def larger(a, b): # 返回较大值
return a if a > b else b def max(x, y, z): # 返回最大值
c = larger(x, y) # 嵌套调用,调用larger()
return larger(c, z)
六、函数的嵌套定义
嵌套定义,即在函数内部定义函数,例:
def outer():
def inner():
print('inner')
inner() outer()
根据依赖倒置原则,嵌套定义的内部函数可以使用外部函数的变量,但是对外部函数中不可变数据类型的变量的修改,将不能再使用global声明:
def outer():
a = 1 def inner():
global a
a = 2
inner()
print(a) outer()
print(a)
结果:
可以看到,在函数内部定义的函数,使用global声明变量,变量依然是全局变量。
若想修改外部函数的变量,则不能使用global修饰了,而应用nonlocal:
a = 0 def outer():
a = 1 def inner():
nonlocal a
a = 2
inner()
print(a) outer()
print(a)
结果:
nonlocal只能用于局部变量,找上层中离当前函数最近一层的局部变量
声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量
七、第一类对象(first-class object)
第一类对象指:
- 可在运行期创建
- 可用作函数参数或返回值
- 可存入变量的实体
在python中,函数满足以上3点,因此是第一类对象。
八、闭包
闭包的概念:嵌套函数,内部函数调用外部函数的变量。例:
def outer():
a = 1 def inner():
print(a)
print(inner.__closure__) outer()
print(outer.__closure__)
结果:
inner函数调用outer函数的变量a,就形成了一个闭包。打印函数的__closure__,出现cell at xxxxxx 就说明是一个闭包。
闭包的常用方式
先看例子:
def outer():
a = 1 def inner():
print(a)
return inner # inner函数作为返回值返回 func = outer() # 实际func指向了inner函数
func() # 调用的是inner
这种在全局调用内部函数的方式是闭包最常用的方式,因为:
1、如果在outer内部调用inner,每次想使用inner都必须频繁地开空间关空间,浪费时间;
2、同时在外部调用闭包可以保护像a这种变量,a虽然不是全局变量,却始终存储在内存里,需要时即可调用,延长了a的生存周期。
九、零散的知识点
1、urlopen
获取网页的源代码:
# 使用urllib模块获取网页内容
# 结合闭包的内容,保存url信息,不需要每次调用重新开辟空间 from urllib.request import urlopen def outer(url):
def inner():
return urlopen(url).read() # 获取网页源代码
return inner func = outer('http://www.taobao.com') # func = inner,url会一直保存在内存
print(func()) # 后续调用即调用inner,url始终是'http://www.taobao.com'
print(func())
print(func())
print(func())
结果:
其实就是目前需要知道的就是:urlopen(网址).read(),得到的网页内容,可以看到是bytes类型的
2、dic循环
for循环dict时,尽量不要循环values(),因为value一般值比较大,会占用更多的内存
十、程序设计六大原则
1、依赖倒置原则(DIP)
依赖倒置原则,就目前自己了解就是内部的依赖于外部的,反之不行。
如命名空间:在局部命名空间里可以使用全局命名空间和内置命名空间里的名字,全局命名空间可以使用内置命名空间里的名字,而内置命名空间只能使用自己空间里的名字。这就是依赖倒置。
DIP是6大原则中最难以实现的原则,它是实现开闭原则的重要途径,DIP没有实现,就别想实现对扩展开放,对修改关闭。在项目中只要记住“面向接口编程”就基本上抓住了DIP的核心。
ps:目前只知道这个原则,后续补充
Python学习 day10的更多相关文章
- python学习Day10 函数的介绍(定义、组成、使用)
今日学习内容: 1.什么是函数 :函数就是一个含有特定功能的变量,一个解决某问题的工具 函数的定义:通过关键字def + 功能名字():代码体(根据需求撰写代码逻辑) 2.为什么要用函数:可以复用:函 ...
- python学习day10
目录 Twisted Redis RabbitMQ Twisted 事件驱动 事件驱动分为两个部分:第一,注册事件:第二,触发事件. 自定义事件启动框架,命名为:"弑君者" ...
- python学习day10 函数Ⅱ(参数&作用域)
函数Ⅱ(参数&作用域) 知识小结: py2与py3的区别 逻辑运算()>not>and>or 字符串翻转切片翻转 is与==区别 git相关 数据类型判断 操作系统:cent ...
- python学习 day10打卡 函数的进阶
本节主要内容: 1.函数参数--动态参数 2.名称空间,局部名称空间,全局名称空间,作用域,加载顺序. 3.函数的嵌套 4.gloabal,nonlocal关键字 一.函数参数--动态传参 形参的第三 ...
- Python学习-day10 进程
学习完线程,学习进程 进程和线程的语法有很多一样的地方,不过在操作系统中的差别确实很大. 模块是threading 和 multiprocessing 多进程multiprocessing multi ...
- Python学习-day10(番外篇) 阻塞IO 非阻塞IO 同步IO 异步IO
这个章节的内容是关于IO的概念,谈一谈什么是 阻塞IO 非阻塞IO 同步IO 异步IO.以下摘要是我对这四种IO的一个形象理解. 场景是去去银行办理业务.节点有三个,1)到银行提交申请:2)取号:3) ...
- 【目录】Python学习笔记
目录:Python学习笔记 目标:坚持每天学习,每周一篇博文 1. Python学习笔记 - day1 - 概述及安装 2.Python学习笔记 - day2 - PyCharm的基本使用 3.Pyt ...
- python学习之旅
python学习分类 python基础 +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...
- Python学习--04条件控制与循环结构
Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...
随机推荐
- javascrip总结42:属性操作案例: 点击盒子,改变盒子的位置和背景颜色
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- HDU 5119 Happy Matt Friends(DP || 高斯消元)
题目链接 题意 : 给你n个数,让你从中挑K个数(K<=n)使得这k个数异或的和小于m,问你有多少种异或方式满足这个条件. 思路 : 正解据说是高斯消元.这里用DP做的,类似于背包,枚举的是异或 ...
- windows10个性化设置
任务栏DIY 日期显示样式 字体
- 编写高质量代码改善C#程序的157个建议——建议117:使用SSL确保通信中的数据安全
建议117:使用SSL确保通信中的数据安全 SSL(Secure Socket Layer)最初是由NetScape公司设计的,用于Web安全的网络协议.目前它已经广泛应用到各类网络传输通信中了.SS ...
- _I、_O、_IO的含义
转自:http://blog.csdn.net/daa20/article/details/42339695 __I. __O .__IO是什么意思? 这是ST库里面的宏定义,定义如下: #defin ...
- Hadoop的Windows伪分布式学习
解压hadoop-2.7.2.zip,不是tar.gz,前者是Windows所用的 解压到路径,设置环境变量 HADOOP_HOME=E:\hadoop-2.7.2\ HADOOP_USER_HOME ...
- 修改阿里云ECS服务器的系统时区
1.前提 由于公司有在印尼的项目,所以购买了阿里云在新加坡机房的服务器(在印尼还没有),印尼当地使用的是东七区的时间,所以领导要求修改阿里云ECS系统的时区. 2.动手 修改阿里云ECS服务器系统的时 ...
- WC的基本功能实现.(Java)
我的GitHub地址:https://github.com/Yuetao1219/lessons WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写 ...
- 终端工具putty访问vmware centos系统
当我们安装好后,可以通过shell来输入命令行来操作centos,当我们一般为了方便可以用终端进行远程连接虚拟机. 软件下载:http://www.chiark.greenend.org.uk/~sg ...
- ListControl的用法
ListControl 控件可在窗体中管理和显示列 表项.可控制列表内容的显示方式,能够以图标和表格的形式显示数据.打开ListControl控件的属性窗口,在Styles选项卡中的View属性中 可 ...