【Python】不常用知识汇总
python 内置函数
map()
- map 函数中传入多个参数
def plus(a, b):
c = a + b
return c
c= [1, 2]
d =[3, 5]
res = map(plus, c, d)
# 注意python3map函数返回一个迭代器,直接输出需转换成列表
list(res)
>>> [4, 7]
re1, re2 = map(plus, c, d)
re1, re2
>>> (4,7)
- *map()表示将包内的参数解压
sorted() 排序
a =[[1,2],[4,5],[3,2],[5,9],[6,1]]
sorted(a, key = lambda x:[x[1],x[0]],reverse=True)
>>> [[5, 9], [4, 5], [1, 2], [3, 2], [6, 1]]
any() 和 all()
- any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。
- all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False。
A = [0,2,3,5]
b = [i for i in A if i > 0]
c = all(i == 1 for i in A)
d = any(i == 0 for i in A)
print(b, c, d)
>>>[2, 3, 5] False True
*的作用
a, *b = [1,2,34]
a, b
>>> (1, [2, 34])
open
使用open 打开文件时的一些参数:
r、w、a为打开文件的基本模式,对应着只读、只写、追加模式;
b、t、+、U这四个字符,与以上的文件打开模式组合使用,二进制模式,文本模式,读写模式、通用换行符,根据实际情况组合使用、
字符 | 含义 |
---|---|
r或rt | 文本模式读(默认) |
rb | 二进制文件 |
w或wt | 文本模式写,打开前文件存储被清空 |
a | 追加模式,只能写在文件末尾 |
a+ | 可读写模式,写只能写在文件末尾 |
w+ | 可读写,与a+的区别是要清空文件内容 |
r+ | 可读写,与a+的区别是可以写到文件任何位置 |
标准库
datetime 模块
datetime 标准库在未指定tz可选参数时,会按照操作系统的时区显示时间。未显示指定时区的软件在跨时区使用时,会造成预期外的效果。
from datetime import datetime, timezone
print(datetime.now(tz = timezone.utc))
copy模块 - 深拷贝和浅拷贝
- 浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。
- 深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
需要import copy模块。
浅拷贝
- 使用数据类型本身的构造器:list、set、dict
list1 = [1, 2, 3]
list2 = list(list1)
print(id(list1), id(list2))
print([id(x) for x in list1], [id(y) for y in list2])
>>>2360182899840 2360166555584
[2362209757488, 2362209757520, 2362209757552] [2362209757488, 2362209757520, 2362209757552]
- 使用 copy.copy() 函数:适用于任何数据类型
- 关于元组、字符串:使用 tuple() 或者切片操作符 ‘:’ 不会创建一份浅拷贝,因为它开辟新的内存存储的是原对象的引用
tuple1= (1, 2, 3)
tuple2 = (tuple1)
print(tuple2)
print(id(tuple1), id(tuple2))
print([id(x) for x in tuple1], [id(y) for y in tuple2])
>>>(1, 2, 3)
2360182831680 2360182831680
[2362209757488, 2362209757520, 2362209757552] [2362209757488, 2362209757520, 2362209757552]
- 切片操作符 ‘:’ 不能用于字典和集合完成浅拷贝,列表可以。
- 对数据采用浅拷贝的方式时,如果原对象中的元素不可变,那倒无所谓;但如果元素可变,浅拷贝通常会出现一些问题
list1 = [[1, 2], (30, 40)]
list2 = list(list1)
list1.append(100)
print("list1:",list1)
print("list2:",list2)
>>> list1: [[1, 2], (30, 40), 100]
>>> list2: [[1, 2], (30, 40)]
list1[0].append(3)
print("list1:",list1)
print("list2:",list2)
>>> list1: [[1, 2, 3], (30, 40), 100]
>>> list2: [[1, 2, 3], (30, 40)]
list1[1] += (50, 60)
print("list1:",list1)
print("list2:",list2)
>>> list1: [[1, 2, 3], (30, 40, 50, 60), 100]
>>> list2: [[1, 2, 3], (30, 40)]
深拷贝
Python 中以 copy.deepcopy() 来实现对象的深度拷贝
import copy
list1 = [[1, 2], (30, 40)]
list2 = copy.deepcopy(list1)
list1.append(100)
print("list1:",list1)
print("list2:",list2)
>>>list1: [[1, 2], (30, 40), 100]
>>>list2: [[1, 2], (30, 40)]
list1[0].append(3)
print("list1:",list1)
print("list2:",list2)
>>>list1: [[1, 2, 3], (30, 40), 100]
>>>list2: [[1, 2], (30, 40)]
list1[1] += (50, 60)
print("list1:",list1)
print("list2:",list2)
>>>list1: [[1, 2, 3], (30, 40, 50, 60), 100]
>>>list2: [[1, 2], (30, 40)]
os 模块
路径操作
函数 | 描述 |
---|---|
os.path.abspath(path) | 返回path的绝对路径 |
os.path.normpath(path | 归一化 path 的表法形式,统一使用\作为分隔符 |
os.path.dirname(path) | 返回 path 中的目录名称 |
os.path.basename(path | 返回 path 中的最后的文件名称 |
os.path.join(path1, path2) | 连接两个或更多的路径名组件 \ os.path.join (“D:/”, “/pye/test.py”) >>>D:/pye/test.txt |
环境参数
函数 | 描述 |
---|---|
os.getcwd() | 返回程序的当前路径 |
os.listdir(path_name) | 将路径下所有文件存到list中 |
解决不同系统的路径差异
windows:
unix:/
imprt os
file_name = 'tmp.text'
file_path2 = os.getcwd() + os.sep + file_name
file_path3 = os.path.join(os.getcwd(), file_name)
Python 参数知识(变量前加星号的意义)
python类class
Python中类的私有属性和受保护属性
-
类的私有成员拒绝从类外部环境访问。它们只能在类的内部处理。
-
类的公有成员(通常是在类中声明的方法)可从类的外部访问。调用公有方法需要相同类的对象。私有实例变量和公共方法的这种安排确保了数据封装的原理。
-
类的受保护成员可以从该类内部访问,也可以用于其子类。不允许其他环境访问它。这样可以使子类继承父类的特定资源。
Python没有有效限制访问任何实例变量或方法的机制。
- Python规定了在变量/方法名称前加单下划线的约定,以模拟受保护访问说明符的行为。
- Python规定了在变量/方法名称前加双下划线的约定,以模拟私有访问说明符的行为。
super().init()
super()是继承父类,那么super().init()代表不用实例化就可以调用父类的__init__()方法来对子类进行初始化,那么这就相当于我们实例化了一个对象,那当然需要给super().init()指定它的参数了,那么这样一来上面的两种方法就更好理解了。
第一种方法super().init(wargs)我们使用了任意数目的关键字参数符号wrags来传入参数
第二种方法super().init(owner, year, model)我们使用了有限的参数直接进行传入
更好的方式:super().init(*wargs, **kwargs)
ref
_init_函数以及参数self
类变量、实例变量、局部变量
- 类中、所有函数(方法)之外:此范围定义的变量,称为类属性或类变量;
- 类中,所有函数(方法)内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
- 类中,所有函数(方法)内部:以“变量名=变量值”的方式定义的变量,称为局部变量。
类变量
类变量的特点是,所有类的实例化对象都同时共享类变量,也就是说,类变量在所有实例化对象中是作为公用资源存在的。类变量的调用方式有 2 种,既可以使用类名直接调用,也可以使用类的实例化对象调用(这个方法不推荐)。
class Person :
# 下面定义了2个类变量
name = "love is love"
add = "yes"
# 下面定义了一个say实例方法
def say(self, content):
print(content)
'''
此程序中,name和add就属于类变量
'''
使用类名 .属性进行调用。同时还可以看到,通过类名不仅可以调用类变量,也可以修改它的值。
class Person :
# 下面定义了2个类变量
name = "love is love"
add = "yes"
# 下面定义了一个say实例方法
def say(self, content):
print(content)
#使用类名直接调用
print(Person.name)
print(Person.add)
#修改类变量的值
Person.name = "sad"
Person.add = "no"
print(Person.name)
print(Person.add)
'''
love is love
yes
sad
no
'''
实例变量
实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。
class Person :
def __init__(self):
self.name = "love is love"
self.add = "yes"
def say(self, content):
self.eir='two'
此 Person类中,name、add 以及 eir 都是实例变量。其中,由于 init() 函数在创建类对象时会自动调用,而 say() 方法需要类实例对象手动调用。因此,Person类的实例对象都会包含 name 和 add 实例变量,而只有调用了 say() 方法的实例对象,才包含 eir 实例变量。
局部变量
除了实例变量,类方法中还可以定义局部变量。和前者不同,局部变量直接以“变量名=值”的方式进行定义,例如:
class Price :
def count(self,money):
sale = 0.8*money
print("优惠后的价格为:",sale)
a=Price()
a.count(100)
'''
优惠后的价格为: 80.0
'''
通常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。
cls和self的不同及使用
@staticmethod或@classmethod的区别
类的普通方法,第一个参数需要self参数表示自身。
- @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。*不需要访问实例,需要访问类属性或者方法。
- @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。*不需要访问实例,不需要访问类属性或者方法。
@abstractmethod 抽象类
异常的类型定义
- BaseException:这个异常类型就是所有异常的基类,在自定义异常类时也需要去继承这个类,当使用它作为异常捕获的类型时就会自动捕获所有异常。
- IOError:该异常类型的意思就是在文件IO流传输出现问题时就会捕获到的异常,一般来说打开文件和读写文件都有可能引发这种异常类型。
- KeyError:在python中看到key关键字就可以知道这个异常类型是由字典所引发的了,它的意思就是在访问了字典中不存在的键时会捕获异常。
- TypeError:这是最常见也是最容易被引发的异常类型了,在对象比较或者是执行任意表达式时,只要对象数据类型和需求不对上就会引发这个类型的异常。
- OverflowError:在python中无论是整数还是浮点数,它们能够参与数学计算的值都是有着长度上限的,当结果或者是数字的长度超出数据类型规定值时就会引起OverflowError类型的异常。
- NameError:这个异常类型被引发的原因就在于访问了当前程序中不存在的变量,name指代的就是变量名。
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
其实,在上述表格中列出的异常中,也具备一定的层次关系,我们可以通过下图来了解一下。
- raise介绍
- 在 Java 中,我们可以使用 throw 语句主动抛出异常,那么在 Python 中,是否也有类似的关键字呢?答案是肯定的。接下来,我们就来了解一下 raise 关键字。在编码过程中,我们可以使用 raise 语句主动触发异常。具体的语法可以参考如下格式:
raise [Exception [, args [, traceback]]]
异常类型转换???
with 类
ref
可以实现上下文管理。
理解Python中的GIL
python中的模块、库、包有什么区别?
- 模块,英文为Modules,本质上是一个Python程序,以.py作为文件后缀。任何py文件都可以作为一个模块
- Python包,就是里面装了一个.py文件的文件夹。在比较大型的项目中常常需要编写、用到大量的模块,此时我们可以使用包(Package)来管理这些模块。
- 库实质就是一个包
编码和解码
三方库 chardet
可用于辅助检测文件编码类型
修饰器
代码工程
启动文件头
可指定运行此文件的解释器版本。
# !/usr/bin/python3.7
# !/usr/bin/env python
为启动文件设置执行入口
一个 Python 文件有两种使用方法, 第一是直接作为脚本执行,第二是通过在其它 py 文件中导入该文件调用执行。
而 if name == 'main’ 的作用就是控制这两种情况的代码执行过程。
简言之:if __name __== 'main’下的代码只有在被作为脚本执行的情况下才会执行,第二种情况时不会执行的。