一、列表
1.删除列表中的元素:
-
用 del 删除元素会导致列表的剩余元素(从删除元素的后面元素开始)的索引发生变化,一般不建议使用。
-
用 remove 或 pop 方法移除可不会发生溢出列表长度的错误,remove只会移除首先遍历到的元素,pop() 括号内不写入值时,默认删除最后一个元素,加入就按索引删除元素
-
列表切片,取到最后一个元素
lis=[3::] #取索引为3到最后的元素,注意冒号之间没有数字 lis=[len(lis)-1::-1] #倒着取所有元素,包含最后元素,只要倒着取,一定要加负数的步长
-
range() 倒着遍历列表到最后一个元素
for i in range(len(lis)-1,-1,-1) #注意各个数字
2.输出列表中元素的索引:
- 当列表中有重复的元素时,使用for i in lis_1: 循环时,当要输出i的索引时,若此时i为列表中的重复的元素,则重复的元素的索引会一样即相等,因为系统默认lis_1.index(i)这里的i是一个列表中值,只会输出列表中的最先遍历到的i的索引。
二、字符串
1.切割字符串:
-
切割字符串时,会生成新的列表,原字符串不变化。
-
字符串的内置方法中,凡是对字符串做修改的操作,字符串本身不会发生变化,想要得到变化后的结果,就要新赋值给一个变量。
也可当做当对不可变的数据类型做修改操作时,这个不可变的数据类型本身不会发生变化,想要得到变化的结果,需要把变化的东西赋值给一个变量
-
字符串转换成列表,不用再遍历字符串了。 如:
s='abcd ef ,g' lis=list(s) print(lis) #打印结果: #['a', 'b', 'c', 'd', ' ', 'e', 'f', ' ', ',', 'g']
2. 字符串也可以进行比较,先按首字母比较,相同就比较第二位字母。
三、BUG
- debug:定位bug,不一定是定位的那一行出错了
四、 读取文本文件
txt文档按行读取时(f.readline()),利用字符串的strip方法切割,把换行符切掉,再利用split方法切割,就可以生成新列表,这样就可以处理按行存储的信息
-
修改文本文件的原理
with open('test.txt', 'r', encoding='utf8') as fr,open('test_swap.txt', 'w', encoding='utf8') as fw: # 再大的文件都能修改 data = fr.read() fw.write(data) import os os.remove('test.txt') os.rename('test_swap.txt', 'test.txt')#先是要修改的文件名字,后是修改后的文件名字,replace 也是如此。
五、一些小的技巧
1. 字符串
-
把字符串的字母都变大写
s='ab cd,f' s=s.upper() #注意,一定一定一定要重新赋值一下,或者直接打印print(s.upper()),否则打印print(s),还是小写的
-
把字符串的字母都变小写
用 lower() 方法
2. 运算
-
print(1.2 - 1.0 == 0.2) # False #010101010 01010101010# # # 010101010 - 01010101010 # 一些差错# # print(round(1.2 - 1.0)) # 浮点数运算时造成的不确定尾数 小数不比整数,小数的二进制非常复杂,所有当两个小数进行算术运算的时候,会出现错误,这个计算的结果无限接近0.2,但是不等于0.2,因此打印返回的是 Fales 而且小数保留两位的时候,不会四舍五入,只有整数有四舍五入。 但是我们可以用下面的方法得到0.2 就是先把两个运算的浮点数变成整数之后在进行运算。最后再除以10的倍数 n = (1.2*10 - 1.0*10)/10 print(n)
3.Python自带的一些东西
-
Python中只要定义变量就会创建新的内存空间,以下为两种特例
Python里的小整数池,在Python启动时就自动为[-5,256]分配内存空间,也就是说,在这个区间内的整数,它们的内存地址被写死,不会改变。
而Pycharm中,把这个小整数池扩大了,在很短的一段时间内定义一个变量值相同的变量,他们的内存地址相同。
-
Python中每个数据类型的数据都有对应的布尔值,
0 / None / 空(空字符、空列表、空字典、空元组) /Falese这些对应的布尔值都为False,其他的为True
-
存不是目的,取才是目的
-
深浅拷贝:
列表,字典等数据类型的内置方法中的 .copy方法都是浅拷贝
lt2 是 lt1的浅/深复制对象 : 就是lt2 复制了lt1 lt2 = copy.copy(lt1) lt2 = copy.deepcopy(lt1)
4. 散列表(哈希表)
字典的key 和集合的元素 都是基于散列表来存储的。索引字典和集合无序,不重复。
六、 集合
乱序:当集合中只有正整数的时候,按升序排序。有正负整数时,正整数升序排序,负数乱序排序,且,且负数在正数后面开始排序。当集合中有正浮点数和符浮点数时,都是按乱序排列,正的排在负的前,正浮点数会乱序在正整数中。
七、 re模块
# findall match search 的区别:
s = 'abcd abcddd abc'
print(re.findall('abcd*', s))
# ## match: 从开头找一个,找得到就不找了 ;找不到报错 --》
# s = 'ab abcddd abc'
# res = re.match('abcd*', s)
# print(res.group())
## search: 从字符串找一个,就不找了
s = 'ab abcddd abc'
res = re.search('abcd*', s)
print(1115555,res)
print(res.group())
八 、迭代器与生成器
#除了数字类型,所有数据类型都是可迭代对象
#为什么要有迭代器对象:提供了 不依赖索引取值的 手段
生成器都是可以用迭代进行取值的,如__next__()
,for循环,还可以使用强制类型转换,转换成列表就可以直接打印出来生成器中的元素。
#for循环原理,本质是可控的while循环
dic = {'a':1,'b':2,'c':3}
dic_iter = dic.__iter__()
while True:
try:
print(dic_iter.__next__())
except StopIteration:
break
# 生成器 自定义range方法
def re_range(start,stop,step):
while start < stop:
yield start
start += step
for i in re_range(0,10,2):
print(i)
九、 循环导入问题和解决办法
-
导模块,模块永远只会开辟一次内存空间,所以当发生循环导入的情况时,不会出现内存满了了的错误,只会发生死循环的错误。 循环导入原理:模块永远只会开辟一次 ; from m1 import 必须得执行m1.py中所有代码,当两个模块互相导入时,就有可能会发生死循环。 1. 在m1中运行m2模块 2. 在m2中运行m1模块 1. 在m1中运行m2模块 2. 在m2中运行m1模块 ...
-
解决方法
# 第一种解决方法: # m1.py下: x = 10 from m2 import y print('m1:', x, y) # 第一种解决方法: # m2.py下: y = 20 from m1 import x print('m2:',x,y) # 第二种: 定义函数阶段只检测语法,不执行代码 # m1.py下: def f1(): from m2 import y print('m1:', x, y) x = 10 f1() # 第二种解决方法: # m2.py 下: def f2(): from m1 import x print('m2:', x, y) y = 20
十、 函数和类
-
函数在调用的时候才开辟名称空间,执行函数内部的代码
-
类是在定义的时候就会开辟名称空间(把类内部的名称全部丢进类的名称空间里),执行类内部的代码。
-
名称空间的执行(生成)顺序:
内置——》全局——》局部
-
名称空间的搜索顺序:
先当前位置 局部——》全局——》内置——》报错 (不可逆)
-
模块的搜索顺序:
内存中的模块——》内置模块——》自定义模块
-
对象中名称的搜索顺序:
-
先对象自己的名称空间——》实例化产生对象的类的名称空间——》父类的名称空间(有多个父类时,按照继承父类的顺序查找)
-
当类中有
self.func()
时,还会重新开始从对象开始按上面的顺序搜索
-
-
在类中的定义的函数,类自己调用它是它就是普通的函数(function)。当对象调用它时,它是绑定方法 (bound method),且类和不同的对象调用同一个函数时,他们(如
Student.func stu1.func stu2.func
)的内存地址都不同
十一、 装饰器的特性
对于二层装饰器,多次使用这个装饰器时,装饰器中 两个函数之间的代码,只会在第一次调用装饰器时执行一次,仅这一次,只会调用这个装饰器,会直接从第二个函数运行。
十二、 面向对象之 反射
对象.__dict__
只返回对象自己的属性(即通过self.属性
的这些属性),就是不包过继承的类中类自己的属性
类.__dict__
只返回类自己的属性
hasattr
和 getattr
,判断对象时,会查找对象自己的,对象自己没有就去找类的。
十三、 面向对象之 魔法方法(类的内置方法)
__getattr__: 会在执行程序时遇到 对象.属性 或者 getattr 方法时,并且 “属性没有” 的情况下才会触发,对象.属性 或者 getattr 的返回值永远是None。
__getattribute__ : 会在执行程序时遇到 对象.属性 或者 getattr 方法 时,无论 “属性有或者没有” 的情况下都会触发。无论属性有没有,对象.属性 或者 getattr 的返回值永远是None,使用这两个方法,对象.属性永远不会报错。
当 __getattr__ 和 __getattribute__ 同时存在,只会触发 __getattribute__ 。
__delattr__ : 会在执行程序时遇到删除对象属性(即 del 对象.属性 【属性是对象自己的或者类的】 )时触发
而且 del 对象.属性 并没有删除该属性
del 类名.属性 会删除该属性 ,删除类的属性不会触发 __delattr__
__del__ : 会在要销毁对象时触发 。如:(1) del 对象名 。
(2)程序执行结束,因此这种情况会在最后执行该方法的代码
十四、 python的一些特点
十五、小知识点
- 在SQL中,字段为枚举类型时,枚举的内容只能用字符串,不能为数字型。
- 在自定义元类时,如果只对要限制的类的名称空间做一个判断,只需要
def __init__(self,class_name,class_bases,class_dic)
,之后直接在下面进行判断,最后再继承父类即type类的__init__
。若要对要限制的类的名称空间进行修改,则需要定义def __new__(cls,class_name ,class_bases,class_dic)
,在其下面写修改内容,最后返回return type.__new__(cls , class_name , class_bases,class_dic)
。
十六、文件单位
PB = 1024 TB = 1024^2 GB = 1024^3 MB = 1024^4 KB = 1024^5 bytes = 8*1024^5