一、变量赋值及命名规则
① 声明一个变量及赋值
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # _author_soloLi 4 name1="solo" 5 name2=name1 6 print(name1,name2) 7 name1 = "hehe" 8 print(name1,name2)
#name1的值为hehe,name2的值为solo
② 变量命名的规则
1 1、变量名只能是 字母、数字或下划线的任意组合 2 2、变量名的第一个字符不能是数字 3 3、以下关键字不能声明为变量名['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global','if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield']
二、字符编码
python解释器在加载 .py 文件中的代码时,会对内容进行编码(默认ascill)
ASCII: 最多只能用 8位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号。显然ASCII码无法将世界上的各种文字和符号全部表示。
Unicode: 它为每种语言中的每个字符设定了统一并且唯一的二进制编码,规定虽有的字符和符号最少由 16 位来表示(2个字节),即:2 **16 = 65536,注:此处说的的是最少2个字节,可能更多。
UTF-8:
是对Unicode编码的压缩和优化,他不再使用最少使用2个字节,而是将所有的字符和符号进行分类:ascii码中的内容用1个字节保存、欧洲的字符用2个字节保存,东亚的字符用3个字节保存...
注:python2.x版本,默认支持的字符编码为ASCll python3.x版本,默认支持的是Unicode,不用声明字符编码可以直接显示中文。
扩展:字符编码和转码,bytes和str区别
Python 3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用str和bytes(类似int和long之间自动转换),正是这使得两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也不能将字符串传入参数为字节包的函数(反之亦然)。这是件好事。不管怎样,字符串和字节包之间的界线是必然的,下面的图解非常重要,务请牢记于心:
字符串可以编码成字节包,而字节包可以解码成字符串:
View Code
为什么要进行编码和转码?
由于每个国家电脑的字符编码格式不统一(列中国:GBK),同一款软件放到不同国家的电脑上会出现乱码的情况,出现这种情况如何解决呢?! 当然由于所有国家的电脑都支持Unicode万国码,那么我们可以把Unicode为跳板,先把字符编码转换为Unicode,在把Unicode转换为另一个国家的字符编码(例韩国),则不会出现乱码的情况。当然这里只是转编码集并不是翻译成韩文不要弄混了。
① Python3.0进行编码转换(默认Unicode编码)
View Code
② Python2.0中的编码转换(默认ascii编码)
View Code
三、用户交互及字符串拼接
View Code
对比分析:
1、% :无法同时传递一个变量和元组,又是要加()来保证不抛出typeerror异常
2、+ :每增加一个一个+就会开辟一块新的内存空间
3、.fomat :不会出现上述问题,有时使用为了兼容Python2版本。如使用logging库
四、循环语句(if、while、for、三元运算)
View Code
五、基本数据类型
【总结】常见的数据类型有哪些?主要操作方法有哪些?
一、整型
如: 18、73、84
类型常用功能:
View Code
更多功能:
View Code
二、长整型
如:2147483649、9223372036854775807
类型常用功能:
View Code
更多功能:
View Code
注:跟C语言不同,Python的长整数没有指定位宽,即:Python没有限制长整数数值的大小,但实际上由于机器内存有限,我们使用的长整数数值不可能无限大。自从Python2.2起,如果整数发生溢出,Python会自动将整数数据转换为长整数,所以如今在长整数数据后面不加字母L也不会导致严重后果
三、浮点型
如:3.14、2.88
类型常用功能:
View Code
更多功能:
View Code
四、字符串
如:'wupeiqi'、'alex'、'solo'
类型常用功能:
View Code
更多功能:
View Code
五、列表
如:[11,22,33,44,55]、['wupeiqi', 'alex','solo']
1、创建列表:
View Code
2、列表类常用功能:
① 切片
View Code
② 追加
View Code
③ 插入
View Code
④ 修改
View Code
⑤ 删除
View Code
⑥ 扩展
View Code
⑦ 拷贝
View Code
⑧ 统计
View Code
⑨ 排序和翻转
View Code
⑩ 获取下标
View Code
六、元组
如:(11,22,33,44,55)、('wupeiqi', 'alex','lzl')
1、创建元组:
View Code
2、元组类常用功能:
View Code
七、字典 无序
如:{'name': 'wupeiqi', 'age': 18} 、{'host': 'solo.solo.solo.solo', 'port': 80}
注:字典一种key:value 的数据类型,也称键值对。字典dict是无序的,key值必须是唯一的,不能有重复。循环时,默认循环的是key
1、创建字典
View Code
2、字典类常用功能:
① 增加
View Code
② 修改
View Code
③ 删除
View Code
④ 查找value值
View Code
⑤ 字典多级嵌套
View Code
⑥ 循环
View Code
八、集合
如:{'solo', 33, 'alex', 22, 'eric', 'wupeiqi', 11}
注:集合是一个无序的,不重复的数据组合。去重性,把一个列表变成集合,就自动去重了。关系测试,测试两组数据之前的交集、差集、并集
1、创建集合
View Code
2、集合类常用功能
① 添加
View Code
② 删除
View Code
3、集合关系测试
① 交集
View Code
② 并集
View Code
③ 差集
View Code
④ 子集、父集
View Code
⑤ 对称差集
View Code
⑥ 运算符做关系测试
View Code
六、模块初识
Python有大量的模块,从而使得开发Python程序非常简洁。类库有包括三中:
① 、Python内部提供的模块
②、业内开源的模块
③、程序员自己开发的模块:Python脚本的名字不要与模块名相同
1、sys模块(系统内置)
① sys.argv 用来捕获执行python脚本时传入的参数
② sys.stdin 标准信息输入
③ sys.stdout 标准定向输出
④ sys.stdout.flush 强制刷新标准输出缓存
View Code
2、os模块(与系统进行交互)
① os.dir、os.popen调用当前系统命令
3、platform模块(识别当前运行的系统)
七、运算符
1、算数运算:
八、深浅拷贝剖析
1、对象赋值
(创建列表变量Alex,变量包含子列表,通过变量Alex给变量solo赋值,然后对变量Alex的元素进行修改,此时solo会有什么变化呢?)
View Code
初始条件:
Alex
= ["Alex", 28, ["Python", "C#", "JavaScript"]]
对象赋值: solo = Alex #直接赋值
对象赋值结果:
solo
= [
"Alex"
, 28, ["Python", "C#", "JavaScript"]]
对象赋值时是进行对象引用(内存地址)的传递,被赋值的变量并没有开辟新内存,两个变量共用一个内存地址
修改对象赋值:solo = [
'Mr.Wu'
, 28, ['Python', 'C#', 'JavaScript',
'CSS'
]]
str是不可变类型,所以当修改元素Alex为Mr.Wu时,内存地址发生改变;list是可变类型,元素['Python', 'C#', 'JavaScript', 'CSS']修改完后,内存地址没有改变
2、浅拷贝 (创建列表变量Alex,变量包含子列表,通过copy模块的浅拷贝函数copy()对变量Alex进行拷贝,当对Alex进行操作时,此时solo会如何变化?)
View Code
初始条件:
Alex
= ["Alex", 28, ["Python", "C#", "JavaScript"]]
浅拷贝: solo = copy.copy(Alex) #通过copy模块里面的浅拷贝函数copy()
浅拷贝结果:
solo
= [
"Alex"
, 28, ["Python", "C#", "JavaScript"]]
浅拷贝时变量solo新建了一块内存(10201848),此内存记录了list中元素的地址;对于list中的元素,浅拷贝会使用原始元素的引用(内存地址)
修改浅拷贝: solo = [
'Mr.Wu'
, 28, ['Python', 'C#', 'JavaScript',
'CSS'
]]
str是不可变类型,所以当修改元素Alex为Mr.Wu时,内存地址发生改变;list是可变类型,元素['Python', 'C#', 'JavaScript', 'CSS']修改完后,内存地址没有改变
3、深拷贝 (创建列表变量Alex,变量包含子列表,通过copy模块的深拷贝函数deepcopy()对变量Alex进行拷贝,当对Alex进行操作时,此时solo会如何变化?)
View Code
初始条件:
Alex
= ["Alex", 28, ["Python", "C#", "JavaScript"]]
深拷贝: solo = copy.deepcopy(Alex) #通过copy模块里面的深拷贝函数deepcopy()
深拷贝结果:
solo
= [
"Alex"
, 28, ["Python", "C#", "JavaScript"]]
深拷贝时变量solo新建了一块内存(10201848),此内存记录了list中元素的地址;但是,对于list中第三个元素(['Python', 'C#', 'JavaScript'])重新生成了一个地址(6203512),此时两个变量的第三个元素的内存引用地址不同
修改深拷贝: solo = [
'Mr.Wu'
, 28, ['Python', 'C#', 'JavaScript',
'CSS'
]]
str是不可变类型,所以当修改元素Alex为Mr.Wu时,内存地址发生改变;list是可变类型,元素['Python', 'C#', 'JavaScript', 'CSS']修改完后,内存地址没有改变,但是Alex和solo在第三个元素引用的本就不同
4、对于拷贝有一些特殊情况
(1)对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有拷贝这一说
(2)也就是说,对于这些类型,"obj is copy.copy(obj)" 、"obj is copy.deepcopy(obj)"
(3)如果元祖变量只包含原子类型对象,则不能深拷贝
①为什么要拷贝?
答:当进行修改时,想要保留原来的数据和修改后的数据
②数字字符串 和 集合 在修改时的差异? (深浅拷贝不同的终极原因)
答:在修改数据时:
数字字符串:在内存中新建一份数据
集合:修改内存中的同一份数据
③对于集合,如何保留其修改前和修改后的数据?
答:在内存中拷贝一份
④对于集合,如何拷贝其n层元素同时拷贝?
答:深拷贝
九、文件操作
(1)打开文件:
文件句柄 = file('文件路径', '模式')
python中打开文件有两种方式,即:open(...) 和 file(...) ,本质上前者在内部会调用后者来进行文件操作,推荐使用 open。
1、打开文件的模式:
r, 只读模式【默认】
w,只写模式【不可读;不存在则创建;存在则删除内容;】
a, 追加模式【不可读;不存在则创建;存在则只追加内容;】
2、"+" 同时读写某个文件:
r+,可读写文件。【可读;可写;可追加】
w+,写读
a+,追加读
小结
3、"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)
rU
r+U
4、"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)
rb 二进制读
wb 二进制写(ab也一样)
ab
(2)文件操作常用功能:
1、read()、readline()、readlines()的区别
print(info_file.read()) #read参数,读取文件所有内容
print(info_file.readline()) #readline,只读取文章中的一行内容
print(info_file.readlines()) #readlines,把文章内容以换行符分割,并生成list格式,数据量大的话不建议使用
2、seek、tell光标
data = info_file.read() #默认光标在起始位置,.read()读取完后,光标停留到文件末尾
print(info_file.tell()) #tell 获取当前的光标位
info_file.seek(0) #seek 移动光标到文件首部
3、文件循环
for index,line in enumerate(info_file.readlines()): #先把文件内容以行为分割生成列表,数据量大不能用
for line in info_file: #建议使用方法,每读取一行,内存会把之前的空间清空,不会占用太多内存
4、flush 刷新
sys.stdout.flush() #flush 强制刷新缓存到内存的数据写入硬盘
5、truncate 截断
truncate跟光标位置无关,从文件首部开始截取字符;如果是truncate(0)会把文件清空
6、with 语句
为了避免打开文件后忘记关闭,可以通过管理上下文,即:
with open('log','r') as f:
...
如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:
with open('log1') as obj1, open('log2') as obj2:
pass
(3)文件修改方式:
1、把文件读取到内存当中,对内存进行修改,把修改后的内容写入到原文件(旧内容被清空)
2、如果在硬盘上直接写,会进行覆盖,硬盘上不能进行插入,原来的内容不会整体后移,而是直接覆盖掉
3、把文件读取到内存当中,对内存进行修改,把修改的内容另存为新的文件(旧文件保留)
① 另存方式
② r+模式
③ a+模式
十、函数
①格式
1 def 函数名(参数): 2 .... 3 函数体 4 .... 5 return 返回值 6 函数名()
②形参:
def func(name): // name 叫做函数func的形式参数,简称:形参
③实参:
func("solo") // 'solo' 叫做函数func的实际参数,简称:实参
④默认参数:
def stu_register(name,age,course,country="CN") // 位置参数
⑤关键参数:
stu_register(age=22,name='lzl',course="python") // 关键参数必须放在位置参数之后
参数另一种较好的讲解!
⑥动态参数/非固定参数(*args 和 **kwargs):
1 (1)*args:*args会把多传入的实参变成一个元组的类型;即使传入的是list类型也会变成元组,成为元组中的一个元素;另函数中有*args与其他形参的时候,*args一定要写到其 他形参的后面,否则传入的实参都会被传入到*args当中打印成元组;还有如果没有多出传入的实参即*args没有值的时候,*args为空,不会报错。 2 (2)**kwargs:**kwargs会把多出的a=b这种类型的实参打印成字典的类型(要区分开与关键参数的区别,关键参数的实参有对应的形参),被当成多余的实参传入到了*args里面,所以**kwargs的值才为空,分别用*inf_list和**info_dict的方式传入到*args、**kwargs当中(stu_register("lzl",*info_list,**info_dict) //传入列表和字典) 3 总结:*args必须放到**kwargs前面(规定);位置参数一定要放到关键参数之前(规定);默认参数不能跟*args、**kwargs一块存在(会报错)。
⑦return 返回值:
如果不执行return,函数的默认返回值为None;当函数执行到return时,函数结束执行
⑧局部变量:
name = "Alex Li" #定义变量name
1 def change_name(name): 2 name = "金角大王,一个有Tesla的男人" #函数内部更改变量 3 函数内部对变量进行更改后,生效范围仅限于函数内部,对外部变量没有影响,这种变量称为局部变量;函数内部也可以让变量全局生效,需要加参数global,这种情况很少用。
⑨递归函数:
如果一个函数在内部调用自身本身,这个函数就是递归函数
条件: 有结束条件、更深一层递归规模比上次递归有所减少、效率不高,递归层次过多会导致栈溢出
1 写一个递归: 2 def func(n1,n2): #获取斐波那契数列100之前的数字 3 if n1 > 100: 4 return 5 print(n1) 6 n3 = n1 + n2 7 func(n2,n3) 8 func(0,1)
⑩ 匿名函数: 不需要显式的指定函数
1 #普通函数 #换成匿名函数 2 def calc(n): calc = lambda n:n**n 3 return n**n print(calc(10) 4 print(calc(10))
⑪高阶函数: 变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
1 def add(x,y,f): 2 return f(x) + f(y) 3 res = add(3,-6,abs) 4 print(res)
⑫内置函数
⑬函数的调用顺序: 被调用函数要在执行之前被定义
1 #函数错误的调用方式 2 def func(): #定义函数func() 3 print("in the func") 4 foo() #调用函数foo() 5 func() #执行函数func() 6 def foo(): #定义函数foo() 7 print("in the foo") 8 9 #函数正确的调用方式 10 def func(): #定义函数func() 11 print("in the func") 12 foo() #调用函数foo() 13 def foo(): #定义函数foo() 14 print("in the foo") 15 func() #执行函数func()
⑭高阶函数: 1、某一函数当做参数传入另一个函数中。2、函数的返回值包含一个或多个函数
⑮内嵌函数: 在一个函数体内创建另外一个函数(内嵌函数中定义的函数在全局中是无法直接执行的)
⑯装饰器:
本质是函数(装饰其他函数),为其他函数添加附加功能的。
遵循原则: 1.不能修改被装饰函数的源代码 2.不能修改被装饰函数的调用方式
组成:装饰器由高阶函数+内嵌函数组成
⑰生成器: 调用时才会生成相应数据的机制,称为生成器:generator
应用:可通过yield实现在单线程的情况下实现并发运算的效果(协程)
协程
⑱迭代器
可迭代对象:可以直接作用于for循环的对象:Iterable
可以直接作用于for循环的数据类型有:1、集合数据类型,如list、tuple、dict、set、str等;2、生成器,包括generator和带yield的generator function;
可以用isinstance()去判断一个对象是否是Iterable对象
1 2 3 |
|
迭代器:
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
用isinstance()判断一个对象是否是Iterator对象
1 2 3 |
|
小结:
1、凡是可作用于for循环的对象都是Iterable类型;
2、凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
3、集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象;
4、Python的for循环本质上就是通过不断调用next()函数实现的
for循环
等价效果(迭代器)
十一、常用模块
(一)、导入模块: 导入模块的本质就是把python文件解释一遍;导入包的本质就是把包文件下面的init.py文件运行一遍
(二)、常用模块:
(1)time和datatime模块
时间相关的操作,时间有三种表示方式:1、时间戳 1970年1月1日之后的秒,即:time.time()
2、格式化的字符串 2014-11-11 11:11, 即:time.strftime('%Y-%m-%d')
3、结构化时间 元组包含了:年、日、星期等... time.struct_time 即:time.localtime()
1 import time 2 print(time.time()) #时间戳 3 #1472037866.0750718 4 print(time.localtime()) #结构化时间 5 #time.struct_time(tm_year=2016, tm_mon=8, tm_mday=25, tm_hour=8, tm_min=44, tm_sec=46, tm_wday=3, tm_yday=238, tm_isdst=0) 6 print(time.strftime('%Y-%m-%d')) #格式化的字符串 7 #2016-08-25 8 print(time.strftime('%Y-%m-%d',time.localtime())) 9 #2016-08-25 10 print(time.gmtime()) #结构化时间 11 #time.struct_time(tm_year=2016, tm_mon=8, tm_mday=25, tm_hour=3, tm_min=8, tm_sec=48, tm_wday=3, tm_yday=238, tm_isdst=0) 12 print(time.strptime('2014-11-11', '%Y-%m-%d')) #结构化时间 13 #time.struct_time(tm_year=2014, tm_mon=11, tm_mday=11, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=315, tm_isdst=-1) 14 print(time.asctime()) 15 #Thu Aug 25 11:15:10 2016 16 print(time.asctime(time.localtime())) 17 #Thu Aug 25 11:15:10 2016 18 print(time.ctime(time.time())) 19 #Thu Aug 25 11:15:10 2016
1 import datetime 2 print(datetime.date) #表示日期的类。常用的属性有year, month, day 3 #4 print(datetime.time) #表示时间的类。常用的属性有hour, minute, second, microsecond 5 # 6 print(datetime.datetime) #表示日期时间 7 # 8 print(datetime.timedelta) #表示时间间隔,即两个时间点之间的长度 9 # 10 print(datetime.datetime.now()) 11 #2016-08-25 14:21:07.722285 12 print(datetime.datetime.now() - datetime.timedelta(days=5)) 13 #2016-08-20 14:21:28.275460
时间比较
(2)random模块: 生成随机数(验证码)
生成随机数
验证码
(3)os模块: 用于提供系统级别的操作(比如目录、路径等的操作)
os模块
(4)sys模块: 用于提供对解释器相关的操作(比如退出程序、版本信息等)
sys模块
(5)shutil模块: 高级的(文件、文件夹、压缩包)处理模块 (比如文件的拷贝、压缩等)
① shutil.copyfileobj 将文件内容拷贝到另一个文件中,可以部分内容
shutil.copyfileobj
把文件f1里的内容拷贝到f2当中
② shutil.copyfile 文件拷贝
shutil.copyfile
把文件f1里的内容拷贝到f2当中
③ shutil.copymode(src, dst) 仅拷贝权限。内容、组、用户均不变
shutil.copymode
④ shutil.copystat(src, dst) 拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat
⑤ shutil.copy(src, dst) 拷贝文件和权限
shutil.copy
⑥ shutil.copy2(src, dst) 拷贝文件和状态信息
shutil.copy2
⑦ shutil.copytree(src, dst, symlinks=False, ignore=None) 递归的去拷贝文件 拷贝多层目录
shutil.copytree
⑧ shutil.rmtree(path[, ignore_errors[, onerror]]) 递归的去删除文件
shutil.rmtree
⑨ shutil.move(src, dst) 递归的去移动文件
shutil.move
⑩ shutil.make_archive(base_name, format,...) 创建压缩包并返回文件路径,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
源码
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
zipfile 压缩解压
tarfile 压缩解压
ZipFile 源码
TarFile 源码
(6)json 和 pickle模块: 文件只能存二进制或字符串,不能存其他类型,所以用到了用于序列化的两个模块
(7)shelve模块: shelve模块内部对pickle进行了封装,shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式 (可以存储数据、获取数据、给数据重新赋值)
View Code
(8)xml模块: xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单(通过<>节点来区别数据结构)
文件
操作
(9)configparser模块: 用于生成和修改配置文档(很少在程序中修改配置文件)
(10)hashlib模块: 用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
hashlib
hmac 模块
(11)re模块: 用于对python的正则表达式的操作;匹配(动态模糊的匹配);关键是匹配条件
正则表达式
①、match:从起始位置开始去匹配
View Code
②、search:最前面去匹配(不一定是最开始位置),匹配最前
View Code
③、group与groups的区别
View Code
④、findall上述两中方式均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall;findall没有group 用法
View Code
⑤、sub:用于替换匹配的字符串
View Code
⑥、split:根据指定匹配进行分组(分割)
View Code
(12)urllib模块: 提供了一系列用于操作URL的功能(利用程序去执行各种HTTP请求。如果要模拟浏览器完成特定功能,需要把请求伪装成浏览器。伪装的方法是先监控浏览器发出的请求,再根据浏览器的请求头来伪装,User-Agent头就是用来标识浏览器的。)
View Code
十二、面向对象
面向过程编程:
通过代码的层层堆积来实现功能。不易迭代和维护。
函数式编程:
将某功能代码封装到函数中,仅调用函数即可
面向对象编程:
利用“类”和“对象”来创建各种模型来实现对真实世界的描述;使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
经典类、新式类
航班查询
类的特殊成员方法:
① __doc__ 表示类的描述信息
View Code
② __module__ 和 __class__
__module__ 表示当前操作的对象在哪个模块
__class__ 表示当前操作的对象的类是什么
View Code
③ __init__ 构造方法,通过类创建对象时,自动触发执行
④ __del__析构方法,当对象在内存中被释放时,自动触发执行
⑤ __call__ 对象后面加括号,触发执行
注:__init__的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
View Code
⑥ __dict__ 查看类或对象中的所有成员
View Code
⑦ __str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值
View Code
⑧ __getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
View Code
⑨ __new__ \ __metaclass__
1 print type(f) # 输出:表示,obj 对象由Foo类创建 2 print type(Foo) # 输出: 表示,Foo类对象由 type 类创建
f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建
是由 type 类实例化产生那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程
View Code
反射:
通过字符串映射或修改程序运行时的状态、属性、方法。 有以下4个方法
① hasattr(obj,str) 判断一个对象obj里是否有对应的str字符串的方法
② getattr(obj,str) 根据字符串去获取obj对象里的对应的方法的内存地址
View Code
③ setattr(obj,'y','z') obj.y = z 通过字符串添加属性
View Code
④ delattr(obj,str) 删除obj.str 通过字符串删除属性
View Code
十三、Python垃圾回收机制
概述: 和许多其它的高级语言一样,Python使用了垃圾回收器来自动销毁那些不再使用的对象。每个对象都有一个引用计数,当这个引用计数为0时Python能够安全地销毁这个对象
问题点: 由于一次仅能有一个对象被回收,引用计数无法回收循环引用的对象。
解决方案: 弱引用:减少循环引用,减少内存中不必要的对象存在的数量。对象可能在任何时刻被回收。
详细内容