【python]】 基础
python 基础
sort
list.sort(key=None, reverse=False)
key — 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse — 排序规则,reverse = True 降序, reverse = False 升序(默认)。
lst.sort(key=lambda x:x[1]) # 以第二个属性排序
python3没有cmp参数。用functools.cmp_to_key(cmp)替代
cmp方法中用a-b,b-a而不是a<b,b<a,因为对返回值正负值判断
str
strip()方法只能移除首尾的字符串或空白
str.format()
str.split(str=””,num=-1),分割为 n+1 和字符,
封装
用 class/namedtuple 等具名形式封装
类
slots
类的 slots 用于显式地为对象绑定数据成员属性,并不针对每个实例自动生成 dict 和
weakref 。 slots 可以是字符串,可迭代对象,或是以多个成员属性命名的字符串组成的序
列(推荐做法,可以是 tuple 或 list 等等)。可以减少类实例所占用的内存大小
python 中万物皆对象,id,type,value
类也是元类的实例
new 是创建实例,(静态方法),init是初始化(实例方法),调用new后返回实例,再调用init
- 类的属性分为实例属性与类属性两种。
实例属性用于区分不同的实例;
类属性是每个实例的共有属性。
通过类创建的实例修改的类属性后,通过其他实例访问类属性他的值还是没有改变。其实是通过实例修改类属性是给实例创建了一个与类属性同名的实例属性而已,实例属性访问优先级比类属性高,所以我们访问时优先访问实例属性,它将屏蔽掉对类属性的访问。
修改实例的类属性,不会影响类,实际上是覆盖了,实例被创建出来后,修改类的类属性,会影响实例的类属性,因为所有实例共享一份类属性 - 属性的访问限制,Python 私有属性
Python 类中如果有属性不希望被外部访问,我们可以在属性命名时以双下划线开头( __ ),那么该属性就不能使用原变量名访问,使得该属性变为本类私有的(伪私有)。
但,如果一个属性以”xxx“的形式定义,那么它可以被外部访问。以”xxx“定义的属性在 Python 的类中是特殊属性,有很多预定义的特殊属性都是以“xxx”定义,所以我们不要把普通属性用”xxx” 定义。
特殊属性
_ _ name_ _:类的名字(字符串)
_ _ doc _ _ :类的文档字符串
_ _ bases _ _:类的所有父类组成的元组
_ _ dict _ _:类的属性组成的字典
_ _ module _ _:类所属的模块
_ _ class _ _:类对象的类型
以单下划线开头的属性”_xxx”,虽然也可以被外部访问,但,按照习惯,他们不应该被外部访问,遵照编码规范我们也不该在外部访问_xx 或 __xx 属性。
补充说明:加双下划线xx 的属性,可以通过“ _类名xx ”可以访问到属性的值。
单下划线,可被重写,调用子类方法
双下划线,不能被重写,调用的还是父类方法
- 方法的访问限制,Python 私有访问
同属性的访问限制,方法的访问限制也是在方法名前加双下划线 ( __ ),它也是一种伪私有。
- @classmethod、@staticmethod 装饰方法
@classmethod 用来修饰方法。使用在实例化前与类进行交互,但不和其实例进行交互的函数方法上。(可以不创建实例来访问方法)
@staticmethod 用来修饰类的静态方法。使用在有些与类相关函数,但不使用该类或该类的实例。如更改环境变量、修改其他类的属性等。
两者最明显的区别,classmethod 必须使用类的对象(cls)作为第一个参数,而 staticmethod 则可以不传递任何参数
- Python 的 property 使用
property 的有两个作用
装饰器: 在一个函数的前后去执行代码
@xxx 语法糖,简化,多个装饰器装饰函数,遵循先进后出。
- 作为装饰器 @property 将类方法转换为类属性(只读)
- property 重新实现一个属性的 setter 和 getter 方法
1、@property 将类方法转换为只读属性(常用)
使用 property 的最简单的方法是将它作为装饰器来使用。这可以让你将一个类方法转变成一个类属性。
- 继承
函数 super()将返回当前类继承的父类,即 Animal,然后调用init()方法,注意 self 参数已在 super()中传入,在init()中将隐式传递,不能再写出 self。
father 是 Father 类的实例,但不是 Son 的实例
son 是 Son 类的实例,也是 Father 类的实例
- 在继承中基类的构造方法(init()方法)不会被自动调用,它需要在其派生类的构造方法中亲自专门调用,实际上子类若定义了 init 方法是在重写父类的 init 方法。
- 在调用基类的方法时,需要加上 super()
- Python 总是首先查找对应类的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)
- 调用 super 方法才能访问到父类的实例属性,父类的类属性可以直接调用
- 菱形继承用 super 只会调用一次祖父节点的 init 方法
初始化 init 函数的行为
参数 self 是 new()返回的实例
- 如果子类没有定义自己的初始化函数,父类的初始化函数会被默认调用;但是如果要实例化子类的对 象,则只能传入父类的初始化函数对应的参数,否则会出错。
- 如果子类定义了自己的初始化函数,而在子类中没有显示调用父类的初始化函数,则父类的属性不会被初始化
- 如果子类定义了自己的初始化函数,在子类中显示调用父类,子类和父类的属性都会被初始化
new 方法
类准备实例化自身时调用,始终是类的类方法
继承
python 类变量在继承中取值方式如下:
1,如果该变量在该类中有定义,则使用该值。
2,如果没有,将搜索父类,多继承时按照从左到右顺序搜索。搜索过程中如果前面父类的值被重新赋值,则类变量值将改变成该值
os 模块
os.name 查看所运行环境 sys.platform
os.environ 环境变量
os.environ‘HOMEPATH’ os.environ‘PATH’ 用户主目录
os.listdir() 列出目录下的全部路径及文件,默认为当前目录
os.mkdir 新建目录,FileExistsError 异常(目录已存在)FileNotFoundError 异常。(在不存在的路路径下新建)os.makedirs() 递归创建多级路径
os.remove 移除文件
os.removedirs 移除目录
os.makedirs 递归移除目录
os.rename(src, dst) 可以实现剪切功能
os.getcwd() 获取当前目录
ps.chdir 切换当前工作目录为指定路径
os.path 模块
仅仅是对字符串的处理
os.path.join 组合路径
os.path.abspath 传入路径规范化,返回一个符合当前系统格式的字符串,参数为相对路径时会拼接当前工作目录
os.path.relpath ..会被移除
os.path.basename 返回传入路径的最后一个路径名,以/分割
os.path.dirname 返回的是最后一个分隔符前的整个字符串
os.path.split os.path.basename+os.path.dirname
os.path.exists()
模块和包
xxx.py: xxx 为模块名字 xxx.py 为文件名
python 包:有层次的文件目录结构,定义 n 个模块或者子包组成的 python 应用程序执行环境。必须有init.py
import package
from package import XX
from package import _
all属性:由 str 元素组成的 list 变量,限定我们使用 form import _ 导入某个模块时能导出的符号,其他不影响
Python 动态加载模块
动态加载指在程序运行中,动态的加载模块,而不是在运行之前利用 import 或 from … import 的方式加载模块的方式。
动态加载是通过指定模块名进行加载,对比与静态加载,动态加载可以接收一个模块名的字符串,而静态加载必须在运行之前全部加载完成。
- 使用系统函数 import
import(name, globals={}, locals={}, fromlist=[], level=-1) - 使用 importlib 模块
- 使用 exec
注解/装饰器
@property
使用@property 装饰器来创建只读属性,@property 会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,防止属性被修改。
@setter
在@property 后,可以用@xxx.setter 来设置属性
@function 是语法糖,多个@function 装饰同一个函数,本质是 a = f1(f2(a)),参考栈递归。内层装饰器先被定义,后被执行。外层装饰器后被定义,先执行。
异常捕获
finall 一定会执行
except 只有第一个捕获的会执行
在 finally 代码块中,由于直接使用 return、break、continue 语句,或者由于调用方法的异常未处理,
会导致 finally 代码块无法正常结束。非正常结束的 finally 代码块会影响 try 或 catch 代码块中异常的抛出,
也可能会影响函数或方法的返回值。所以要保证 finally 代码块正常结束。
命名规范
除了类,异常是首字母大写,其他都是小写下划线
lower_with_fun: 包,模块,函数方法,函数参数,变量
CapWords:类,异常
全大写+下划线(CAPS_WITH_UNDER):常量
下划线开头:类或者对象的私有成员 1.单下划线开头,外部仍能访问;双下划线开头,解释器会将变量改名字,作用是避免名字冲突;不具有权限控制,外部不能访问
except(e1,e2) try 中捕获多个异常
except[e1,e2] try 中捕获 e1,e1 的执行过程中捕获 e2
模块中的下划线开头的变量不会被 from xxx import yyy 导入,import xxx xxx.yyy 可以使用
is 判断是否指向同一个对象(判断两个对象的 id 是否相等), == 会调用 eq 方法判断是否等价
(判断两个对象的值是否相等)。
基础注意点
列表为空判断 if lst / if len(lst) / if lst == [] ,python 中 False,0,’’,[],{},()都可以视为假
不同类型的对象比较,永远不会相等 [] == False/True => False
型比较 isinstance(item, str),不用 type(item)== str
type()不会认为子类是一种父类类型。isinstance()会认为子类是一种父类类型。
可变对象:list dict set
不可变对象: tuple string int float bool
可变对象重新赋值时,地址没有变
不可变对象重新赋值时,重新开辟了内存空间,地址变了。
函数默认参数:一定要在设置为不可变参数,不然默认调用时有意想不到的错误,因为默认参数在函数定义时就确定下来,之后使用的都是同一个,永远是同一个对象
默认参数的值存放在defaults
实例的dict仅存储与该实例相关的实例属性,
正是因为实例的dict属性,每个实例的实例属性才会互不影响。
类的dict存储所有实例共享的变量和函数(类属性,方法等),类的dict并不包含其父类的属性。
dir()函数会自动寻找一个对象的所有属性,包括dict中的属性。
dict是 dir()的子集,dir()包含dict中的属性。
字典的可以不能为可变对象
闭包: 函数 A 返回了一个函数 B,函数 B 就叫闭包,调用函数 A 时传递的参数为自由变量,自由变量的生命周期结束后不会被回收,保存在closure中
Nonlocal 与 global 的区别在于 nonlocal 语句会去搜寻本地变量与全局变量之间的变量,其会优先寻找层级关系与闭包作用域最近的外部变量。
cProfile 性能分析器
python 中用.来访问和改写类的属性成员时会调用get和set方法,会查找 class.dict。
二次探测再散列处理:有冲突的话,按照 +— n 的平方再次散列探测
线性探测:往后依次找位子放
二次探测:发生冲突时再次探测+1,-1,+4,-4,+9,-9 来处理
增加 global 后,对应的变量不会新建为局部变量。 可变对象没有加 global 的话,重新赋值不会影响全局变量。
函数的参数,命名参数要在所有的位置参数后面
python 没有函数重载,同名的函数会被覆盖
运算符优先级
lambda < or < and < not < in/not in < is/not is < (<.<=,>,>=,!=,==) < | < ^ < & < (>>,<<) < +/- < *, / , % < 正负号 < ~ < **
日志 Logging 默认打印出 WARNING 级别以上的日志
字典推荐用 get 方法,key 不存在时返回值为 None
格式化性能对比: f-string> + > % > format
decimal 库专门处理高精度的库,奇进偶舍
is 和==的区别
is 比较的是 id
==比较的是值相等
python 在交互式界面对小整形【-5,255】有缓存,在脚本式编程不涉及
()不一定是元组,也可以是调整优先级
lambda 函数
lambda 关键字来声明一个匿名函数,可以接收任意数量的参数,但函数只能包含一个表达式
类似 js 的()=>{}
迭代对象
可迭代对象包括迭代器
可迭代对象要有iter方法,迭代器要有iter和next方法
iter()返回当前对象的迭代器类的实例
next()返回迭代的每一步,实现该方法时最后超出边界时要抛出 StopIteration 异常
生成器: 使用了 yield 的函数,返回迭代器,在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保留当前所有的运行信息,返回 yield 的值,并在下一次执行 next()时从当前位置继续运行。
pdb
python 用于调试的包,
b 设置断点,c 继续执行程序到下一个断点,l 查看当前行的代码段,s 进入函数 return/r 执行代码直到从当前函数返回
exit/q 中止并退出, next/n 执行下一行,pp 打印变量的值,help 帮助
正则表达式
re.match(pattern, string, flags=0) 只匹配字符串的开始
re.groups()
re.search(pattern, string, flags=0) 匹配整个字符串
re.compile 编译一个正则表达式
集合操作
a|b 并集
a&b 交集
a^b 去掉交集
a-b 去掉 b’中的
add()
update
remove
编解码
string ->字节码 -> string
bytes: a = b’weqe’
比较操作
- 任意对象都可以计较
- 相同类型的对象,如果是数字型(int/float/long/complex),按大小比较,非数值型,定义了cmp(gt,it),则按照cmp来比较,否则按照地址(id)来比较
- 不同类型的对象,数字类型的对象<其他非数字型的对象。如果都是非数字型的对象,按类型名的顺序比较
- 自定义的类,如果继承自基本类型,按规则 3 比较,否则 old style class < new style class,new-style class 之间按类型名顺序比较,old-style class 之间按照地址进行比较。
- bool 是 int 的子类,且 True=1,False=0, python3 中字符串与任何类型比较都不行
python 链式比较
按照数据表达式的方式进行计算,和 java 等不同
1<22 => 1 < 2 and 22
计较的优先级高于等于
可变参数
任意数量的形参,用*表示
*param: 从此处开始直到结束的所有位置参数(Positional Arguments)都将被收集并汇集成一个称为“param”的元组(Tuple)
**param: 从此处开始直至结束的所有关键字参数都将被收集并汇集成一个名为 param 的字典(Dictionary)
实际调用时,必须全部解构,不然会被当作一个参数处理
解构实参传递
形参正常定义,实参传递元组或者字典时,用*和 **传递
subprocess 模块
子进程
深浅拷贝
lst.copy 或者 list()是浅拷贝,只拷贝第一层
copy.deepcopy 拷贝深层
小数取整
round 四舍五入
floor 向下取整
ceil 向上取整
线程/进程/协程
python 多线程只能并发,不能并行,同一时刻只有一个线程在运行,因为有 GIL。多进程可以并行,每个进程有独立的 GIL
适合 IO 密集型,不适合 cpu 密集型。因为 GIL 的特性,内部对象缺省就是线程安全的。
subprocess
subprocess.call(args, *, stdin= None, stdout = None, stderr = None, shell = False)
运行由 args 参数提供的命令,等待命令执行结束并返回返回码。args 参数由字符串形式提供且有多个命令参数时,需要提供 shell=True 参数,通过列表传参则不需要
subprocess.check_call(args, *, stdin = None, stdout = None, stderr = None, shell = False)
与 call 方法类似,不同在于如果命令行执行成功,check_call 返回返回码 0,否则抛出 subprocess.CalledProcessError 异常。
del
del 方法删除对象时,如果还有引用,不会执行del,在程序结束后自动执行。
特殊方法
hash
len
str
循环
生成二维数组
lst = [[]]*10 错误,乘法将[]这个对象复制了 10 遍。
- 列表推导式
lst = [[] for _ in range(10)] - for 循环 append
for 中的 i 其实是在当前作用域创建了一个变量
decimal 模块
decimal 意思为十进制,这个模块提供了十进制浮点运算支持
- 可以传递给 Decimal 整型或者字符串参数,但不能是浮点数据,因为浮点数据本身就不准确。
- Decimal.from_float
- 通过设定有效数字,限定结果样式
getcontext().prec 确定 - 四舍五入,保留几位小数
Decimal(‘50.1234’).quantize() - Decimal 结果转化为 string
取整:
getcontext().rounding = getattr(decimal,”)
ROUND_CEILING 总是趋向无穷大向上取整
ROUND_DOWN 总是趋向 0 取整
ROUND_FLOOR 总是趋向负无穷大向下取整
ROUND_HALF_DOWN 如果最后一个有效数字大于或等于 5 则朝 0 反方向取整;否则,趋向 0 取整
ROUND_HALF_EVEN 类似于 ROUND_HALF_DOWN,不过,如果最后一个有效数字值为 5,则会检查前一位。偶数值会导致结果向下取整,奇数值导致结果向上取整
ROUND_HALF_UP 类似于 ROUND_HALF_DOWN,不过如果最后一位有效数字为 5,值会朝 0 的反方向取整
ROUND_UP 朝 0 的反方向取整
ROUND_05UP 如果最后一位是 0 或 5,则朝 0 的反方向取整;否则向 0 取整
bisect
bisect_left(lst,x) bisect_right(lst,x)
- lst中没有x, 返回值为x在lst中合适的位置。
bisect_left(lst,x) = bisect_right(lst,x)
ls[index1] > x,ls[index2] > x - lst中只有一个x,bisect_left(lst,x)为x的索引,bisect_right(lst,x)为x的索引+1
- lst有多个x,bisect_left(lst,x)为最左x的索引,bisect_right(lst,x)为最右x的索引+1