python笔记
Posted Justaman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python笔记相关的知识,希望对你有一定的参考价值。
概览:
变量类型:整形,浮点型,字符串,但定义变量时不需要指定类型,在第一次赋值时确定类型
列表、元组(定死了不可改变的列表)、字典,集合(set,无序不可重复);对以上iterable的操作,初始化(按照括号不同来区分,小括号-元组,中括号-列表,大括号-字典),访问,改变,增加,删除
方法,实参,形参;
lambda,map,列表推导式
iterable迭代器,可用列表等来保存其值,也可直接用for等直接拿到其返回值
positional argument:位置参数
关键字:
对比:
列表,sort(iterable)永久排序,sorted()临时排序,进对sorted(iterable)这一句执行是进行排序,后面的不变
字典也有sort()与sorted()
day01
python中():
没有封号’;’,而用回车符来代替,所以一句话结束后开始另一句话必须回车
也没有大括号{},而使用tab来表明在方法内,而没有tab则表示方法结束
而冒号’:’主要是为了像if a<3 : a=2这种就不会出现混乱
def定义方法
变量
不需要定义类型,必须要初始化即赋值;没有字符型char,被并到字符串类型中了
动态类型:在运行期间确定变量的类型,python确定一个变量的类型是在第一次给他赋值的时候;
强类型:有强制的类型定义,一个整数,除非显示的类型转换,否则绝不能将它当作一个字符串
变量赋值,可以同时多个,如a,b = 2,3;c,d = a,b
标准数据类型:数字-int,float;字符串-str ;列表-list ;元组-tuple ;字典-dict ;
除标准类型外,还有方法类型,及自定义类型-类;都包括在class中,即class:’int’,class:’function’,class:type-指类
python中的变量都是一个个对象,如a=1,type(a)则会输出<class \'int\'>
单行注释#,多行注释’’’… …’’’或”””… …”””
字符串,单引号’’和双引号””是等同的,可以进行’+’操作和’*’操作;单行保留格式r’……’,多行’’’……’’’(和注释符号一样)
使用 j
或 J
后缀,可以赋值虚数,但j/J前必须有实数,如2+1j,而不能写成2+j;这样可以和变量j进行区分
列表的长度可变,可存储各类型变量/常量,可用append()改变自身;也可通过’+’与其他列表组合形成新的列表
切片[a:b]是一个很便捷的工具,左右切片位置可以是变量,但a必须小于b,否则为空[]。
切片可用于列表、
range
range(start, stop, step)返回的是range对象,list(range(1,4))返回从1开始,到4之前的3,即[1,2,3]
list(range(5)),默认开始为0,则返回[0,1,2,3,4];
list(range(1,5,2))返回[1,3]
break是结束整个循环体,continue是结束单次循环
形参(位置参数a,默认参数b=1,*c,**d)
默认参数:形参中的赋值的参数,def abc(a,b,c=[],d=4),其中c,d即为默认值参数,调用方法时可传可不传
位置参数:调用函数时根据位置来传递的参数,像上面的a,b,调用是为abc(1,3,…),位置参数必须传值
位置参数在前原则:形参中有位置参数a,与默认参数b=3,默认参数必须在后,即abc(a,b=3),而不能相反
同样的,实参中,位置参数必须在关键字参数之前
注意:默认值只初始化一次,当默认值是一个可变对象(如列表,字典或大多数类的实例)时,方法执行完后不会释放
def f(a,b=[]): b.append(a) return b,
第一次调用f(1)后,输出[1],第二次调用f(2)后,输出[1,2]
形参可接收元组和字典,一个星(*):表示接收的参数作为元组来处理;两个星(**):表示接收的参数作为字典来处理
如:def abc(a,*c,**d): 调用:abc(2,\'asddasff\',car=\'betles\',phone=\'apple\',pc=\'dell\'),a=2,b-元组,c-字典
不过元组会把后面的参数当成元组元素,所以如果传的是键值对,就要用关键字参数;而字典会把关键字参数当成字典元素,
而关键字参数又不能放在位置元素(也即字典参数)前,而直接传又会出错,不清楚为什么,所以暂时没有解决办法;
实参(位置参数a,关键字参数b=3,解包*c,解包**d)
关键字参数:调用方法时,通过“键-值”形式传值的参数,形参中必须有名称一致的默认参数,键值对形式使得可以不用管顺序
实参不可以定义变量,如abc(i=5),但可以是关键字参数,即字母一致,必须是abc(a=5),这里的a=5是参数而非定义
实参中的关键顺字参数序不重要,即可以abc(b=1,a=2)
解包参数列表,即在元组或字典变量前加*或**完成解包,如d=[3,4,5],abc(*d)就可分别把值传到abc(a,b,c)中了
day02
iterable:可迭代的对象,如list,tuple,dict,str,都是iterable(凡是可以for循环的,都是Iterable)
元组,长度和每个元素不能改变,且为圆括号或不用括号,定义,tuple0=(),tuple1=(1,2),tuple2=1,2 一个元素时后面要加逗号,(1,),死的,皆不可变的列表即元组
集合
没有顺序且不可重复
set1 = {‘a’,’b’,’c’},也可用set(iterable)方法-返回集合,但大括号定义时不能为空,因为{}特指字典
增加,add() ,删除remove(),因为没有顺序所以不需要指定位置
可进行逻辑运算& | ^
字典
初始化:a = {‘key1’:value1},添加:a[‘key2’]=value2;也可用dict()方法或列表推导式构建字典
索引指的是根据键而不是位置,键必须是不可变的类型,数字、字符串、不包含可变类型的元组可作为键
键不能重复。两个相同的键,后一个值会被记住
遍历:键-值:for a,b in dict.items():,a,b即分别拿到键与值;整体:for a in items():
不像列表有顺序号,字典靠key来遍历,或者靠value,所以有以下三个方法
keys()方法返回dict_keys类型(iterable,非list,不能索引)而不是列表,需要用list(dict1.keys())后才可以索引;
values(),items()同理,返回值也为iterable
键:for a in dict.keys():,值:for a in dict.values():,
增加,直接dict1[‘key1’] = 1就行了;
删除del dict1[‘key1’],pop(key1)弹出key1所对应的元素,popitem()弹出最后一个元素,为字典独有
列表:
初始化:a = [1,2,3],也可用list1 = list()创建空列表;另外list2 = list(tuple1)可将元组转变为列表
添加:append(x),x是常数;extend(a),追加列表;insert(i, c),i是位置,c可以是常数也可以是列表
删除:remove(x),x是常量且必须存在于要移除列表中,仅移除第一个;
pop()弹出末尾的, pop(i),移除i 位置上的数且返回i 位置上的数
del list1[2]删除2位置上的元素;del list1[i1:i2],根据索引删除,i1和i2是索引;del不是list的方法,是独立的方法
clear()清空列表
index(x),返回第一是x的索引;独有sort()方法,根据字母排序
len(list1)返回列表长度
list1.reverse()将列表翻转
lambda关键字创建小的匿名函数,被局限于只能有一个单独的表达式
c = lambda a, b: a+b (a,b为形参,返回a+b)
map方法
提供了一种创建list的简便方法。创建列表时,列表中的元素来源于其他序列、可迭代对象,相当于用函数创建一个列表
分别将各个iterable的对应元素(如同为第一个元素),传入func方法中,然后依次得到返回的值
map(func, iterable,iterable,……),func为方法,后面至少一个iterable,而iterable的数量和顺序必须与func形参一致
返回值为:传进func的各iterable值计算后的结果,map()返回值为map对象,需要用list(map())等,将返回值保存起来
列表推导式-List Comprehensions
提供了一种创建list的简便方法。创建列表时,列表中的元素来源于其他序列、可迭代对象,相当于用函数创建一个列表
与list(map(func,iterable,…))类似,形如:list([(x, y) for x in [1,2] for y in [3,1] if x != y]),每循环一小次则返回
一个元组,list会将这些全部保存起来,结果为[(1,3),(2,3),(2,1)]
规则:由一对方括号组成,方括号包含一个表达式,其后跟随一个for子句,然后是零个或多个for或if
子句
表达式如(x,y),在展开的形式中为list1.append((x,y)),即表达式是最里面的语句
其中for语句是嵌套的,if为实际语句
列表推导式的嵌套,[[row[i] for row in [[1,2],[3,4]]] for i in range(2)],结果为[[1,3],[2,4]],展开则为:
list2 = []
for i in range(2):
list1 = []
for row in [[1,2],[3,4]]:
list1.append(row[i])
list2.append(list1)
注意,变量名要保持一直,(x,y)与其对应的for x ..for y;row[i]与for row
zip()方法,zip([iterable, ...]),将iterable压缩成元组,可以看作是把列转换为行
解压缩zip(*zip())就是再转一次行列
enumerate方法,list(enumerate(iterable, start)),结果如:[(0,’ab’),(1,’bc’),(2,’ef’)]
比较:
in/not in,is/is not;比较操作符优先级小于算数操作符
级联比较,a < b == c测试a是否小于b并且b是否等于c;and/or/not,逻辑优先级小于比较操作符,且not>and>or
sort()方法仅用在list上,对原有list进行修改,而sorted(iterable)是对所有可迭代的对象,返回新的iterable对象
day03
方法
方法的本质上是对象,可以用变量对其引用,def abc():,a=abc,这样a()与abc()就是等同的,注意与a=abc()的区别
在方法中也可以定义方法,即方法可嵌套,但外部无法直接调用嵌套中的方法
嵌套方法的使用:①仅在主方法内部使用,在方法内部获得/使用嵌套方法的计算结果
②外部使用,先‘return 嵌套方法’,然后a=abc()调用主方法赋值给变量,即可完成在外部调用嵌套方法a(),毋忘加括号
拼接
+,仅限于相同类型,如同为字符串/元组/列表,但不能是字典/集合;
要想输出字符串+列表,必须把列表转换成字符串,如print(‘the list is:’+str([3,4,5,]))
input(‘提示信息’),用户输入
模块-module
导入模块,import module1,调用方法必须加模块名,module.func1
从模块中导入方法或变量,from module1 import func1/var1,调用时可直接用func1/var1而不用加模块名
from xx import xx形式,变量会被加入到当前的命名空间中,所以可能导致覆盖情况发生,故不推荐使用
使用as来避免重名,import module1 as md1,from mod import func/var as f/v
包-package,包是一个有层次的文件目录结构,它定义了由n个模块或n个子包组成的python应用程序执行环境
namespace命名空间,四个:Locals-函数内部,Enclosing-外面一层函数,Globals运行的全局变量,Builtin内置模块空间
LEGB,程序引用某个变量的名字时,就会从名字空间开始搜索,搜索顺序规则便是:LEGB,一层层查找,找到后便停止搜索
装饰器,使得方法变得可扩展,如对方法增加功能等
__name__,它的值由Python解释器设定:
如果脚本文件是作为主程序调用,其值就设为__main__,如果是作为模块被其他文件导入,它的值就是其文件名
locals(),返回局部变量所构成的字典;globals(),返回全局变量所构成的字典
vars(object),返回对象的属性和属性值的字典,没有参数时与locals()方法一致
reduce(function,iterable)方法,根据给定方法对迭代器中元素进行计算
day04
python的动态特性
new_class(name, bases=(), kwds=None, exec_body=None)动态创建类
C.a=1绑定属性,可用setattr(object, name, value)方法,delattr(object, name)删除属性,getattr(object, name)
obj.func1=MethodType(func,obj)绑定方法,绑定给类时方法内部定义的属性是公共的,绑定给实例时则仅此实例独有
类
定义类,”class Car(FatherClass1,FatherClass2): “,类名不一定要大写,但建议用大写
类的实例化,car1=Car(1,2) ,类中有数据属性和方法,数据属性会覆盖同名的方法属性
类中有特殊方法__init__(self,a,b),在实例化时便会自动调用,其中self便是实例化本身,即car1
实例调用方法时会默认把自己传给方法,所以方法的形参至少有一个参数用来接收实例对象,默认用self,也可以用其他名称
但是,但是,在方法中必须要写上self,不然报错,python的设计人员说是为了explicit。。。既然是人家开发的那也没辙了
注意:类的属性为可变对象(如列表,字典和大多数其他类型),只会初始化一次,即类的所有实例共享这一变量
(这与形参的默认值问题类似),当为不可变的基本类型(数字,字符串,元组),不存在这种问题
要避免这种问题,可将其放入__init__()方法中,即self.a=b,b接收的为可变对象,如[1,2,3]
方法
类有三种方法,分别是实例方法,类方法(方法前面加@classmethod),静态方法(方法前面加@staticmethod);
类方法与静态方法类似,当一个函数逻辑上属于一个类又不依赖与类的属性的时候,可以使用staticmethod
实例可调用类方法,类无法调用实例方法:实例创建时包含隐藏参数self,cls,因此三种方法皆可调用
类创建时包含隐藏参数cls而无self,所以只能调用类方法和静态方法;
也可以理解为类仅调用类方法时传入自己,而调其他方法是不传类自己这个参数的,而实例除static外都会传入自己
继承
FatherClass为父类,可以多继承,即传入多个父类对象;方法名一致,则子类的方法覆盖父类的方法
多重继承面临的问题是搜索属性的顺序是怎样的,即MRO-方法解析顺序,MRO经过了几次改变
一代:DFS-深度优先搜索,而DFS会导致‘公共父类(D)的多继承’情况下只能继承无法重写的问题
二代:BFS-广度优先搜索,BFS会导致在‘互不相关的类的多继承’情况下产生单调性问题
而现在的C3使用拓扑排序完全的解决了这两个问题,super()方法指的是MRO表中的下一个类
(参见:http://python.jobbole.com/85685/)
多态,只需有继承即可,与Java不同:不需要父类引用指向子类对象,所以python多态本质和各子类直接调用自己的方法一样
内部类
外部类调用内部类,首先实例化外部类outc,然后outc.inc()即可得到内部类的实例
内部类调用外部类,直接实例化外部类即可调用,因为在内部类中可以检索到外部类
类-内存
实例刚被创建时,命名空间里什么都没有,所引用的变量其实都是存在于类的命名空间中的
而za1.a其实才是把a写到了命名空间中,而这个a与类的a不是同一个
实例方法:id(A.ab) != id(a1.ab) == id(a2.ab),而类方法与静态方法,三个id()都是相等的,很奇怪,待查。。。
vars(object)方法,返回对象属性名称和值的字典,无参数时相当于locals();dir(object),返回对象的属性名称
type()与instance()
isinstance(a, list),判断一个对象是否是一个已知的类型,判断的是类型而不是==;type(a)方法查看对象a的类型
type() 不会认为子类是一种父类类型,不考虑继承关系;isinstance() 会认为子类是一种父类类型,考虑继承关系
is/is not,用于判断两个引用所指的对象是否相同
id()方法,用于获取对象的内存地址,注意是对象而不是对象的引用
__class__,可以获得对象的类型,如a=’a’,则a.__class__返回str
__bases__,可以获得对象的父类,如int.__bases__返回object
Object与Type
如a = 1,a的类型是int,而int的类型是type,而type对象本身的类型是type
创建对象分两种:实例对象由类对象创建出来,而类对象由PyTyObject创建出来
直观的说就是因为可以在运行期间动态的创建类型,所以不能在code时就把类型写死;而这会导致在运行期不知道分配多少内存,所以才有了type来补充;而像Java这种前期已经明确定义好了的,就不需要再额外来一个与Object’势均力敌‘的家伙了
而类型的从属则引出了类-实例,方法instance()判断实例是否属于某个类,不正是在判断类型吗,所以,根据类型的从属关系可以导出如下关系,进而引出元类
元类metaclass
首先,需要明确类也是一种对象,对,python中一切皆对象,只是类这个对象拥有创建对象的能力
所以,元类创建类,类实例化之后成为对象;有点像上帝造了亚当和夏娃,而亚当和夏娃实例化后产生了各种人类
但无论上帝、亚当/夏娃,还是现在的人类,都是对象,有属性、方法
当使用class时编译器自动的创建一个类,但也可以手动的创建,现在不用class了那用什么呢?
对,就是元类,type()便是一个元类,可以用来创建类,所以,元类可以说是创建类的类(深刻理解Python中的元类)
day 05
with obj/func() as var1:
with后面跟对象(跟方法,方法必须返回一个对象),而这个对象要有__enter__和__exit__方法
在执行with代码块中的语句前先执行__enter__()方法,这个方法返回值赋给as后面的变量
然后再执行with内的内容,最后执行__exit__()方法,如果有异常这个方法可以输出异常信息
open(‘filename’,’r/w/a/r+/b’)方法
要对文档进行操作,必须先打开文档,用完之后要关闭
open()方法打开文档且返回文档对象,第一个参数为文档对象名字,可以是相对路径也可以是绝对路径
第二个参数为打开模式,r:只读(默认),w:只写,不存在则创建,存在则清空后写入,a:附加,r+:读写,b:二进制
可用with open(‘filename’) as obj 来操作文件,with可使文档自动关闭,as用来将open()方法返回的对象赋给变量obj
rstrip()用于将字符串后面的空白删除,文档末尾会有个空行,每一行末尾也都有个空行
read(size),size为读取的字节数,会返回读到的字符串,无参数时则会返回文件的内容全部,所以一般都带参数
readline(size),无参数时返回读取到的文件的一行,有参数时与read()方法一样;for a in file_obj,也可得到文件的每一行
readlines()方法,返回文档所有行的列表
write(‘str’),写入str字符串,返回写入的字符个数
tell()方法,返回当前指针位置
seek()方法
用于重置当前指针位置,seek(offset,from_what),offset表示相对于参考点的偏移
from_what为参考点,0:文件开头,1:当前位置,2:文件末尾,默认为0
异常
try … except as e,except可有多个,e即异常对象,可以对其进行打印异常信息等操作
else在没有异常时执行,即except代码与else代码只会执行一个;finally代码则一定会被执行
round(value,num)函数
返回value的num位的小数,与print("%.1f " % 1.95)一致
round(0.5),2.x中保留到离0远的一边,为1;3.x保留到偶数的一边,为0
但特殊数字round出来的结果可能未必是想要的:
round(2.675,2)在2.x与3.x中都为2.67,但应该都是2.68,这是因为浮点数在内存中并不与标定的一样大
可用别的方法:字符串格式化可以做截断使用,例如 "%.2f" % value
不过浮点数的不精确也会影响到print("%.1f " % 1.95)
decimal模块提供了十进制浮点运算支持,from decimal import Decimal
Decimal(2.675)方法,返回实际的精确数,2.67499999999999982
以上是关于python笔记的主要内容,如果未能解决你的问题,请参考以下文章