函数名称空间与作用域
字符编码
产生乱码的原因
1.存取的时候编码方式不一样,只要找到对应的编码数据就可以正常显示
2.存的时候乱码,即存储数据时,出现了当前编码表中无法识别的符号,导致乱码
unicode和utf-8都支持万国语言
unicode 两个字节 固定长度 浪费空间 但是效率高 但是效率高 更适用于内存中
utf-8 可变长度 节省空间 效率相对低 更加适用于网络传输和IO操作
编码与解码
把内存中的Unicode符号 编码成指定的二进制 进行存储 叫做编码
把硬盘上的二进制 解码成Unicode 叫做解码
str.encode() 得到bytes
bytes.decode() 得到str
在python3中字符串变量都是Unicode 所以不会乱码
文件处理
打开文件 open
读 read
写 write
关闭文件 close
with 语法可以简化书写 自动close
r == rt
w == wt
a == at
t表示文本模式 会自动完成 编码和解码操作 读写都是以字符为单位
b表示文本模式 没有编码和解码过程 读写都是以字节为单位 可用于任何文件
函数基础
为什么用函数
代码冗余
结构不清晰,可读性差
扩充性差,维护性差
什么是函数
函数是一段实现某个功能的代码的集合体,相当于生活中的某个工具
必须遵循 先定义 再调用
函数完成语法
def 函数名(参数列表)
'''
文档注释
'''
函数体
return 值
函数定义
有参
当函数体的代码逻辑需要依赖外界的数据才能完成功能时,例如upper()
无参
当函数体的代码逻辑不需要依赖外界的数据才能完成功能时,例如打印99乘法表
空函数
没有函数体的函数称之为空函数 用来在编写程序初期定义程序的结构
函数的调用
1.直接调用 函数名加括号
2.可以在表达式中调用函数
3.print(len('123')) 可以将函数的返回值作为另一个函数的参数
函数参数
形参指的是在函数定义阶段的参数
实参指的是调用函数时传递的值
1.位置参数,有几个就必须传几个,实参会按照顺序依次赋值给形参
2.关键字参数,指的是实参,可以在调用时 按照形参的名字传值,可以打破顺序限制 顺序为(普通,位置,关键字)
3.默认值参数,可以在定义函数时,给形参指定一个值,需要注意默认值应该设置为不可变类型
4.可变长形参
* 可变长的位置形参 特点是可以接收溢出的位置实参,打包为一个元组类型
** 可变长的关键字形参 特点是可以接收溢出的关键字实参,打包为一个字典类型
可变长实参
* 可以跟任何的可迭代类型(str,list,tuple,set,dict),会把后面的值打散成单个元素以位置实参传递给函数
** 可以跟mapping类型(dict),会把后面的字典打散成单个的key-value以关键字实参传给函数
命名关键字参数
当可变长形参后面还有别的参数时,如果它没有默认值,则调用时必须以关键字的形式来传值,这种参数就是命名关键字参数
例如:
def func(*a,b,c)
print(a,b,c)
func(1,2,3,b=4,c=5)
函数返回值
return 返回一个值给函数调用者
可以是一个值 也可以是多个值 也可以什么都不写就一个return会默认返回一个None
不仅可用于返回一个值 还能用于结束一个函数的执行
-----------------------------------------------------------------------------------------
函数嵌套
函数嵌套
嵌套指的是,一个物体包含另一个物体
函数嵌套指的就是一个函数包含另一个函数
按照函数的两个阶段 分为
嵌套调用
指的是 在函数的执行过程中调用了另一个函数
其好处是 可以简化外层大函数的代码,使得结构更清晰
可以将一个大的复杂的功能拆分成多个简单的小功能
嵌套定义
指的是 在函数的函数体中定义了另一个函数
需要注意的是:内部定义的函数只能在内部使用,外界是无法直接访问
唯一的使用场景就是闭包函数,除此之外不要这么写
名称空间
就是存储名字的内存区域
名称空间的分类
内置名称空间
存的是解释器自带的名称,例如print ,len
特点:在程序运行过程中一直有效
生命周期:随着解释器的启动而生效,随着解释器运行结束而失效
全局名称空间
只要是顶着最左边写的,没有任何缩进的,就在全局名称空间中,
特点:在程序运行过程中一直有效
生命周期:随着py文件的执行而生效,随着py文件的执行结束而失效
需要注意的是:在if中如果if是顶着最左边的没有缩进,那么if里面的名字也属于全局
同样的,while ,for, with都是如此
局部名称空间
存的是函数内定义的名字
特点:仅在函数调用时临时有效
生命周期:随着函数的调用而生效,随着函数的调用结束而失效
名称空间的加载顺序
局部 --> 全局 --> 内置
名字的查找顺序
局部 --> 全局 --> 内置
作用域
作用域
域指的是区域,范围 作用域指的是作用区域,作用范围,有效范围
简单的说就是名字的有效范围
存储名词的有三个地方
内置名称空间
全局名称空间
局部名称空间
全局作用域
由于内置名称空间的名字与全局名称空间的名字可以在任何位置来访问,
所以他们两个可以划到同一个范围,称之为全局范围即全局作用域
局部作用域
局部名称空间的名字只能在当前的函数中访问,所以它单独划到一个范围中,
这个范围称之为局部作用范围即局部作用域
global(全局) 与 nonlocal(不使用本地) 关键字
global
当需要在函数内部修改全局中名字的值时需要使用global
注意,必须在使用这个名字之前声明(写)global
nonlocal(不使用本地)
当需要在内层函数中修改外层函数中的名字时就需要使用nonlocal
会一层一层往外层找,直到找到了位置,但是只能找函数中不能找到全局的名字
例如:
a = 100
def func():
global a #声明一下 我要使用全局的a
a = 1
func()
print(a)
---------------------------------------------------------------------------------------------
函数对象
函数对象
目的是为了让你知道函数都可以怎么来使用
面向对象中一句经典语录:万物皆对象,也就是说函数也是对象
函数是第一类对象:
1.能够被调用
2.可以当做容器类型的元素
3.可以当做函数的参数
4.可以当做函数的返回值
函数名除了可以调用外与一个变量名没有本质区别,变量能怎么用,函数名就能怎么用
---------------------------------------------------------------------------------------
闭包函数
闭包 :一个函数将另一个函数关闭在内部,反过来说
一个函数被另一个函数包裹
闭包函数也是一种函数
其特点是:
1.该函数是定义在另一个函数中的
2.该函数包含了队外层函数中的名字的引用,无论在任何位置使用这个函数,其都包含了外部名字引用
满足以上两条就称之为闭包函数
需要注意的是:名字所在的作用域,在函数定义阶段就已经固定了,与调用位置无关
现阶段可以将闭包理解为,另一种为函数体传值的方式
之前只能通过参数给函数传值
现在可以通过闭包的方式
由于名称空间与作用域的特点,内层定义的函数只能在内层函数
而函数对象可以将一个函数作为返回值,使得内部函数也可以被外界使用


浙公网安备 33010602011771号