Python个人总结(基础+进阶)
Python总结
0、python的重载与重写:
何为重载:重载指的是相同的方法名,不同的参数,或不同的参数类型。根据传入的参数的个数与参数的个数来判断使用哪个方法。但是在python中相同的方法名会被覆盖,所以不能实现传统意义上的重载。
运算符重载:是通过改写运算符的魔法方法来实现的
何为重写:重写指的是将继承的方法进行重新编写,覆盖继承的父方法。
1、is 与 ==区别:
- is是判断左右两个值是否是同一对象
- ==是判断左右两个对象的值是否一样
2、全局变量与局部变量
- 全局变量是在全局都能使用,但如果在局部(如函数)进行值得修改赋值,则在这里的函数内部,变量就变成了局部变量。而想要在这里进行重新赋值修改的还是全局变量就要声明全局变量global 变量名。这样接下来修改的就是全局变量。
3、进制转换
- 二进制的转换:bin()
- 八进制转换:oct()
- 十六进制:hex()
4、格式化输出:
- 方法一:print(’%格式1%格式2’ %(变量1,变量2))
- print(‘你好%s我是%d’ %(b,a))
- 这里%s是格式化的字符串
- %d是格式化的数字
- 方法二:print(’{}{}{}’.format(a,b,c))
- print(‘是是是{}{}’.format(a,b)) =>是是是1哈哈
- 当然format也有其他的用法(这样直接就能随意的给a赋指定的值):
- a = ‘我{}是{}’
- a.format(a,b)
5、可变参数与不可变参数
- 整数,字符串,元组是不可变参数,当作为参数传入函数中,对其修改的话,在外函数而言这些传入的参数不会发生改变,除非使用了全局变量声明。
- 对于一些可变的参数,比如列表和字典,集合。这样的话,传入这样的参数进去,对其修改,则相当于是地址传递,对这个参数修改(不是重赋值)而是进行添加等,是对地址进行修改。也就是说,传入的是全局变量,主外都是一个变量。
- 也就是说参数重新赋值会变成局部变量,而不重新赋值,对原参数进行修改(只有列表和字典进行修改,也就是添加删除),它仍然是全局变量。
附加:深拷贝与浅拷贝
首先,对于某些不可变类型:整型,浮点型,字符串。
a =1 b =1 a is b =>True a =1.0 b =1.0 =>False a = 'a' b ='a' =>True
为什么呢?
原因:这三种类型,是不可变的,所以不论是赋值,还是b=a这种形式,都是对某一个值的引用。比如:a=1,b=1都是对1的引用,所以为什么a is b是True。又比如a = ‘a’,b=‘a’ 无论是变量a还是变量b都是对’a’的引用,所以a is b为True。具体为什么a = 1.0,b=1.0 而a is b为False,是因为表面上看都是对1.0的引用,但实际上对于浮点数而言,在超过一定位数之后,数字可能就不是0了,比如1.0可能在计算机内部是:1.00000000000000321这样的。所以,其实是对两种浮点型的引用所以为False
其次,对于某些不可变类型Tuple元组,以及可变类型,列表List,字典dict,集合set。对其进行重新赋值,都是创建一个新的对象。
list1 = [1,2,3] list2 = [1,2,3] list1 is list2 =>False 等等
会产生False的原因,就是对于这些类型,就算是重新赋的值是一样的,也是重新创建一个对象,分配内存与地址。id是不一样的。
以此引出copy浅拷贝与deepcopy深拷贝。
- copy.copy()复制当前的对象的内容,然后赋值到新建一个对象上。适用于简单对象,即列表,元组,字典,集合等内部不再包含这些类型的数据。比如[1,2,3]就不包含,[1,[1,2]]就列表对象里包含列表对象,这样就不适合使用copy(),因为copy()不会复制子对象,子对象还是同一引用。
- copy.deepcopy()深复制当前的对象的内容,然后赋值到新建一个对象上。适用于复杂对象,即列表,元组,字典,集合等内部包含这些类型的数据,比如适用于[1,[1,2]]这样的类型。这样在复制时,不仅会复制[1,[1,2]]这个外对象,即对这个外对象进行添加删除都是对新对象的添加删除与原对象无关。而且,也会复制子对象[1,2]到新建的子对象上。因此对[1,2]修改也是对新子对象的修改,与原子对象无关。
6、列表方法总结:
- len(list1) :返回列表的长度
- max(list1) :返回列表的最大值
- min(list1) :返回列表的最小值
- list(其他类型) :将其他类型转成列表
- list1.append() :列表添加一个值
- list1.count(obj) :统计指定对象在列表的个数
- list1.extend(list2) : 等价于list1+list2 将列表2的内容添加到列表1的后面
- list1.insert(index,obj) : 在指定的索引添加指定的值
- list1.pop() :默认将末尾的值弹出
- list1.pop(index) :弹出指定位置的值
- list1.remove(obj) :删除指定的对象。
- list1.reverse() :翻转列表的元素
- list1.sort() :对列表进行排序,默认是升序。当然可以指定reverse = True来改成降序
7、集合{} =>set方法总结:
<可变不可变都可用的>
s.issubset(t) :测试s是不是t的子集
s.issuperset(t) :测试t是否是s的子集
s.union(t) :返回s与t想并的结果
s.intersection(t) :返回s与t的交集
s.difference(t) :返回s中有但t中没有的,即s-t
s.symmetric_difference(t) :返回s有t没有,t有s没有的,这些元素
<仅用于可变集合>
s.update(t) : 将集合t的元素添加到s中。
s.intersection_update(t) :返回s 中仅包括 s 和 t 中共有的成员
s.difference_update(t) : 返回s 中包括仅属于 s 但不属于 t 的成员
s.symmetric_difference_update(t) : s 中包括仅属于 s 或仅属于 t 的成员
s.add(obj) :在集合中添加一个对象
s.remove(obj) :在集合中删除一个对象
s.discard(obj) :将 obj 从 s 中删除,如果 s 中不存在 obj,也没事儿_
s.pop() :弹出操作:移除并返回 s 中的最后一个元素
s.clear() :清除操作:清除 s 中的所有元素
特殊:sorted(集合) 会返回一个排好序的包含集合的值得列表。原集合不改变。
8、元组方法总结(元组是不可变的)
- cmp(tuple1,tuple2) :比较两个元组是否一样
- len(tuple1) :返回元组的长度
- max(tuple1) :返回元组最大的值
- min(tuple1) :返回元组最小值
- tuple(其他类型) :将其他类型转成元组
- 元组虽然不能被修改,但可以通过元组1+元组2 生成一个新的元组,来间接修改。
9、字符串方法总结
方法名 | 方法解释 |
---|---|
capitalize() | 把字符串的第一个字符改为大写 |
casefold() | 把整个字符串的所有字符改为小写 |
center(width) | 将字符串居中,并使用空格填充至长度 width 的新字符串 |
count(sub[, start[, end]]) | 返回 sub 在字符串里边出现的次数,start 和 end 参数表示范围,可选。 |
encode(encoding=‘utf-8’, errors=‘strict’) | 以 encoding 指定的编码格式对字符串进行编码。 |
endswith(sub[, start[, end]]) | 检查字符串是否以 sub 子字符串结束,如果是返回 True,否则返回 False。start 和 end 参数表示范围,可选。 |
expandtabs([tabsize=8]) | 把字符串中的 tab 符号(\t)转换为空格,如不指定参数,默认的空格数是 tabsize=8。 |
find(sub[, start[, end]]) | 检测 sub 是否包含在字符串中,如果有则返回索引值,否则返回 -1,start 和 end 参数表示范围,可选。 |
index(sub[, start[, end]]) | 跟 find 方法一样,不过如果 sub 不在 string 中会产生一个异常。 |
isalnum() | 如果字符串至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False。 |
isalpha() | 如果字符串至少有一个字符并且所有字符都是字母则返回 True,否则返回 False。 |
isdecimal() | 如果字符串只包含十进制数字则返回 True,否则返回 False。 |
isdigit() | 如果字符串只包含数字则返回 True,否则返回 False。 |
islower() | 如果字符串中至少包含一个区分大小写的字符,并且这些字符都是小写,则返回 True,否则返回 False。 |
isnumeric() | 如果字符串中只包含数字字符,则返回 True,否则返回 False。 |
isspace() | 如果字符串中只包含空格,则返回 True,否则返回 False。 |
istitle() | 如果字符串是标题化(所有的单词都是以大写开始,其余字母均小写),则返回 True,否则返回 False。 |
isupper() | 如果字符串中至少包含一个区分大小写的字符,并且这些字符都是大写,则返回 True,否则返回 False。 |
join(sub) | 以字符串作为分隔符,插入到 sub 中所有的字符之间。 |
ljust(width) | 返回一个左对齐的字符串,并使用空格填充至长度为 width 的新字符串。 |
lower() | 转换字符串中所有大写字符为小写。 |
lstrip() | 去掉字符串左边的所有空格 |
partition(sub) | 找到子字符串 sub,把字符串分成一个 3 元组 (pre_sub, sub, fol_sub),如果字符串中不包含 sub 则返回 (‘原字符串’, ‘’, ‘’) |
replace(old, new[, count]) | 把字符串中的 old 子字符串替换成 new 子字符串,如果 count 指定,则替换不超过 count 次。 |
rfind(sub[, start[, end]]) | 类似于 find() 方法,不过是从右边开始查找。 |
rindex(sub[, start[, end]]) | 类似于 index() 方法,不过是从右边开始。 |
rjust(width) | 返回一个右对齐的字符串,并使用空格填充至长度为 width 的新字符串。 |
rpartition(sub) | 类似于 partition() 方法,不过是从右边开始查找。 |
rstrip() | 删除字符串末尾的空格。 |
split(sep=None, maxsplit=-1) | 不带参数默认是以空格为分隔符切片字符串,如果 maxsplit 参数有设置,则仅分隔 maxsplit 个子字符串,返回切片后的子字符串拼接的列表。 |
splitlines(([keepends])) | 在输出结果里是否去掉换行符,默认为 False,不包含换行符;如果为 True,则保留换行符。。 |
startswith(prefix[, start[, end]]) | 检查字符串是否以 prefix 开头,是则返回 True,否则返回 False。start 和 end 参数可以指定范围检查,可选。 |
strip([chars]) | 删除字符串前边和后边所有的空格,chars 参数可以定制删除的字符,可选。 |
swapcase() | 翻转字符串中的大小写。 |
title() | 返回标题化(所有的单词都是以大写开始,其余字母均小写)的字符串。 |
translate(table) | 根据 table 的规则(可以由 str.maketrans(‘a’, ‘b’) 定制)转换字符串中的字符。 |
upper() | 转换字符串中的所有小写字符为大写。 |
zfill(width) | 返回长度为 width 的字符串,原字符串右对齐,前边用 0 填充。 |
10、字典方法总结:
方法 | 方法描述 |
---|---|
dict1.clear() | 清除字典内所有元素 |
dict1.copy() | 返回字典的一个浅复制 |
dict.fromkeys(键序列,值) | 生成字典,每个键对应都对应这个值 |
dict1.get(健) | 返回键对应的值 |
dict1.has_key(键) | 判断字典是否有这个键 |
dict1.items | 返回生成的可比遍历列表。比如:[(1, ‘a’), (2, ‘b’)] |
dict1.keys() | 返回所有的键,以列表的形式 |
dict1.setdefault(键) | 返回键对应的值,没有就将这个键加入字典,值为None |
dict1.update(dict2) | 将字典2添加入字典1 |
dict1.values() | 返回字典的所有值,以列表的形式 |
dict1.pop(键) | 弹出字典的指定的键 |
dict1.popitem() | 随机弹出一对键和值 |
11、标准异常总结
AssertionError | 断言语句(assert)失败 |
---|---|
AttributeError | 尝试访问未知的对象属性 |
EOFError | 用户输入文件末尾标志EOF(Ctrl+d) |
FloatingPointError | 浮点计算错误 |
GeneratorExit | generator.close()方法被调用的时候 |
ImportError | 导入模块失败的时候 |
IndexError | 索引超出序列的范围 |
KeyError | 字典中查找一个不存在的关键字 |
KeyboardInterrupt | 用户输入中断键(Ctrl+c) |
MemoryError | 内存溢出(可通过删除对象释放内存) |
NameError | 尝试访问一个不存在的变量 |
NotImplementedError | 尚未实现的方法 |
OSError | 操作系统产生的异常(例如打开一个不存在的文件) |
OverflowError | 数值运算超出最大限制 |
ReferenceError | 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 |
RuntimeError | 一般的运行时错误 |
StopIteration | 迭代器没有更多的值 |
SyntaxError | Python的语法错误 |
IndentationError | 缩进错误 |
TabError | Tab和空格混合使用 |
SystemError | Python编译器系统错误 |
SystemExit | Python编译器进程被关闭 |
TypeError | 不同类型间的无效操作 |
UnboundLocalError | 访问一个未初始化的本地变量(NameError的子类) |
UnicodeError | Unicode相关的错误(ValueError的子类) |
UnicodeEncodeError | Unicode编码时的错误(UnicodeError的子类) |
UnicodeDecodeError | Unicode解码时的错误(UnicodeError的子类) |
UnicodeTranslateError | Unicode转换时的错误(UnicodeError的子类) |
ValueError | 传入无效的参数 |
ZeroDivisionError | 除数为零 |
12、文件的打开方式与方法
打开方法:
打开模式 | 执行操作 |
---|---|
‘r’ | 以只读方式打开文件(默认) |
‘w’ | 以写入的方式打开文件,会覆盖已存在的文件 |
‘x’ | 如果文件已经存在,使用此模式打开将引发异常 |
‘a’ | 以写入模式打开,如果文件存在,则在末尾追加写入 |
‘b’ | 以二进制模式打开文件 |
‘t’ | 以文本模式打开(默认) |
‘+’ | 可读写模式(可添加到其他模式中使用) |
‘U’ | 通用换行符支持 |
常见文件方法
文件对象方法 | 执行操作 |
---|---|
f.close() | 关闭文件 |
f.read([size=-1]) | 从文件读取size个字符,当未给定size或给定负值的时候,读取剩余的所有字符,然后作为字符串返回 |
f.readline([size=-1]) | 从文件中读取并返回一行(包括行结束符),如果有size有定义则返回size个字符 |
f.write(str) | 将字符串str写入文件 |
f.writelines(seq) | 向文件写入字符串序列seq,seq应该是一个返回字符串的可迭代对象 |
f.seek(offset, from) | 在文件中移动文件指针,从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节 |
f.tell() | 返回当前在文件中的位置 |
f.truncate([size=file.tell()]) | 截取文件到size个字节,默认是截取到文件指针当前位 |
13、系统模块OS的方法
函数名 | 使用方法 |
---|---|
os.getcwd() | 返回当前工作目录 |
os.chdir(path) | 改变工作目录 |
os.listdir(path=’.’) | 列举指定目录中的文件名(’.‘表示当前目录,’…'表示上一级目录) |
os.mkdir(path) | 创建单层目录,如该目录已存在抛出异常 |
os.makedirs(path) | 递归创建多层目录,如该目录已存在抛出异常,注意:'E:\a\b’和’E:\a\c’并不会冲突 |
os.remove(path) | 删除文件 |
os.rmdir(path) | 删除单层目录,如该目录非空则抛出异常 |
os.removedirs(path) | 递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常 |
os.rename(old, new) | 将文件old重命名为new |
os.system(command) | 运行系统的shell命令 |
os.walk(top) | 遍历top路径以下所有的子目录,返回一个三元组:(路径, [包含目录], [包含文件]) |
以下是支持路径操作中常用到的一些定义,支持所有平台 | |
os.curdir | 指代当前目录(’.’) |
os.pardir | 指代上一级目录(’…’) |
os.sep | 输出操作系统特定的路径分隔符(Win下为’\’,Linux下为’/’) |
os.linesep | 当前平台使用的行终止符(Win下为’\r\n’,Linux下为’\n’) |
os.name | 指代当前使用的操作系统(包括:‘posix’, ‘nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’) |
在os的子模块os.path模块关于路径常用的方法
函数名 | 使用方法 |
---|---|
os.path.basename(path) | 去掉目录路径,单独返回文件名 |
os.path.dirname(path) | 去掉文件名,单独返回目录路径 |
os.path.join(path1[, path2[, …]]) | 将path1, path2各部分组合成一个路径名 |
os.path.split(path) | 分割文件名与路径,返回(f_path, f_name)元组。如果完全使用目录,它也会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在 |
os.path.splitext(path) | 分离文件名与扩展名,返回(f_name, f_extension)元组 |
os.path.getsize(file) | 返回指定文件的尺寸,单位是字节 |
os.path.getatime(file) | 返回指定文件最近的访问时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) |
os.path.getctime(file) | 返回指定文件的创建时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) |
os.path.getmtime(file) | 返回指定文件最新的修改时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) |
以下为函数返回 True 或 False | |
os.path.exists(path) | 判断指定路径(目录或文件)是否存在 |
os.path.isabs(path) | 判断指定路径是否为绝对路径 |
os.path.isdir(path) | 判断指定路径是否存在且是一个目录 |
os.path.isfile(path) | 判断指定路径是否存在且是一个文件 |
os.path.islink(path) | 判断指定路径是否存在且是一个符号链接 |
os.path.ismount(path) | 判断指定路径是否存在且是一个挂载点 |
os.path.samefile(path1, paht2) | 判断path1和path2两个路径是否指向同一个文件 |
14、魔法方法总结(以下所有方法均为:方法)
魔法方法 | 含义 |
---|---|
基本的魔法方法 | |
new(cls[, …]) | 1. new 是在一个对象实例化的时候所调用的第一个方法 2. 它的第一个参数是这个类,其他的参数是用来直接传递给 init 方法 3. new 决定是否要使用该 init 方法,因为 new 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 new 没有返回实例对象,则 init 不会被调用 4. new 主要是用于继承一个不可变的类型比如一个 tuple 或者 string |
init(self[, …]) | 构造器,当一个实例被创建的时候调用的初始化方法 |
del(self) | 析构器,当一个实例被销毁的时候调用的方法 |
call(self[, args…]) | 允许一个类的实例像函数一样被调用:x(a, b) 调用 x.call(a, b) |
len(self) | 定义当被 len() 调用时的行为 |
repr(self) | 定义当被 repr() 调用时的行为 |
str(self) | 定义当被 str() 调用时的行为 |
bytes(self) | 定义当被 bytes() 调用时的行为 |
hash(self) | 定义当被 hash() 调用时的行为 |
bool(self) | 定义当被 bool() 调用时的行为,应该返回 True 或 False |
format(self, format_spec) | 定义当被 format() 调用时的行为 |
有关属性 | |
getattr(self, name) | 定义当用户试图获取一个不存在的属性时的行为 |
getattribute(self, name) | 定义当该类的属性被访问时的行为 |
setattr(self, name, value) | 定义当一个属性被设置时的行为 |
delattr(self, name) | 定义当一个属性被删除时的行为 |
dir(self) | 定义当 dir() 被调用时的行为 |
get(self, instance, owner) | 定义当描述符的值被取得时的行为 |
set(self, instance, value) | 定义当描述符的值被改变时的行为 |
delete(self, instance) | 定义当描述符的值被删除时的行为 |
比较操作符 | |
lt(self, other) | 定义小于号的行为:x < y 调用 x.lt(y) |
le(self, other) | 定义小于等于号的行为:x <= y 调用 x.le(y) |
eq(self, other) | 定义等于号的行为:x == y 调用 x.eq(y) |
ne(self, other) | 定义不等号的行为:x != y 调用 x.ne(y) |
gt(self, other) | 定义大于号的行为:x > y 调用 x.gt(y) |
ge(self, other) | 定义大于等于号的行为:x >= y 调用 x.ge(y) |
算数运算符 | |
add(self, other) | 定义加法的行为:+ |
sub(self, other) | 定义减法的行为:- |
mul(self, other) | 定义乘法的行为:* |
truediv(self, other) | 定义真除法的行为:/ |
floordiv(self, other) | 定义整数除法的行为:// |
mod(self, other) | 定义取模算法的行为:% |
divmod(self, other) | 定义当被 divmod() 调用时的行为 |
pow(self, other[, modulo]) | 定义当被 power() 调用或 ** 运算时的行为 |
lshift(self, other) | 定义按位左移位的行为:<< |
rshift(self, other) | 定义按位右移位的行为:>> |
and(self, other) | 定义按位与操作的行为:& |
xor(self, other) | 定义按位异或操作的行为:^ |
or(self, other) | 定义按位或操作的行为:| |
反运算 | |
radd(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rsub(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rmul(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rtruediv(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rfloordiv(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rmod(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rdivmod(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rpow(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rlshift(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rrshift(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rand(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
rxor(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
ror(self, other) | (与上方相同,当左操作数不支持相应的操作时被调用) |
增量赋值运算 | |
iadd(self, other) | 定义赋值加法的行为:+= |
isub(self, other) | 定义赋值减法的行为:-= |
imul(self, other) | 定义赋值乘法的行为:*= |
itruediv(self, other) | 定义赋值真除法的行为:/= |
ifloordiv(self, other) | 定义赋值整数除法的行为://= |
imod(self, other) | 定义赋值取模算法的行为:%= |
ipow(self, other[, modulo]) | 定义赋值幂运算的行为:**= |
ilshift(self, other) | 定义赋值按位左移位的行为:<<= |
irshift(self, other) | 定义赋值按位右移位的行为:>>= |
iand(self, other) | 定义赋值按位与操作的行为:&= |
ixor(self, other) | 定义赋值按位异或操作的行为:^= |
ior(self, other) | 定义赋值按位或操作的行为:|= |
一元操作符 | |
pos(self) | 定义正号的行为:+x |
neg(self) | 定义负号的行为:-x |
abs(self) | 定义当被 abs() 调用时的行为 |
invert(self) | 定义按位求反的行为:~x |
类型转换 | |
complex(self) | 定义当被 complex() 调用时的行为(需要返回恰当的值) |
int(self) | 定义当被 int() 调用时的行为(需要返回恰当的值) |
float(self) | 定义当被 float() 调用时的行为(需要返回恰当的值) |
round(self[, n]) | 定义当被 round() 调用时的行为(需要返回恰当的值) |
index(self) | 1. 当对象是被应用在切片表达式中时,实现整形强制转换 2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 index 3. 如果 index 被定义,则 int 也需要被定义,且返回相同的值 |
上下文管理(with 语句) | |
enter(self) | 1. 定义当使用 with 语句时的初始化行为 2. enter 的返回值被 with 语句的目标或者 as 后的名字绑定 |
exit(self, exc_type, exc_value, traceback) | 1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么 2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作 |
容器类型 | |
len(self) | 定义当被 len() 调用时的行为(返回容器中元素的个数) |
getitem(self, key) | 定义获取容器中指定元素的行为,相当于 self[key] |
setitem(self, key, value) | 定义设置容器中指定元素的行为,相当于 self[key] = value |
delitem(self, key) | 定义删除容器中指定元素的行为,相当于 del self[key] |
iter(self) | 定义当迭代容器中的元素的行为 |
reversed(self) | 定义当被 reversed() 调用时的行为 |
contains(self, item) | 定义当使用成员测试运算符(in 或 not in)时的行为 |
15、各种格式的表示:
符号 | 说明 |
---|---|
%c | 转成字符 |
%r | 优先用repr()函数进行字符串转换 |
%s | 转成字符串 |
%d | 转成有符号十进制数 |
%u | 转成无符号十进制数 |
%o | 转成无符号八进制数 |
%x | 转成无符号十六进制(小写) |
%X | 转成无符号十六进制(大写) |
%e | 转成科学计数法 |
%f | 转成浮点数 |
%% | 将%转义输出 |
注意的是:%.nf是保留n位小数
16、类的私有方法,类方法,静态方法等
方法/属性的类型 | 方法表示 | 特点 |
---|---|---|
类方法 |
@classmethod def 方法体: |
则这个方法一般是类的方法,即类.方法。一般不给实例化对象来使用。 |
私有方法 | def __方法名: | 在方法名的前面加__表示这是私有方法。所谓私有方法,就是只能由类本身来使用。其子类不能使用,实例化的对象也不能使用。 |
保护方法 | def _方法名: | 在方法名前面加_表示这是保护方法。所谓的保护方法,就是只能类本身或子类来使用。其实例化对象不能使用 |
私有变量 | __变量 | 在变量前加__表示这是一个私有变量,所谓私有变量就是只能类本身来访问,其子类与实例化对象都不能使用。 |
保护变量 | _变量 | 在变量前加_表示,这是一个保护变量,所谓保护变量就是只能由类和子类使用。实例化对象不能使用。 |
静态方法 | @staticmethod def 方法体: | 静态方法就会将这个方法与类的关系切断,即传入的self失效,它就变成了普通函数,与写在类之外的函数一模一样,不再是类的方法了。 |
注意:在python中,(特殊)对象直接访问私有变量的方法:对象._类名__变量
附加:
子类继承父类时,调用父类的方法1:父类名.方法(self,参数) =>适用于使用父 类的__init__,并且是多个父类
方法2:super(子类名,self).方法(参数) =>适用于 使用父类的init,并且是一个父类,方法 里不用写self
17、位运算符
位运算符 | 意思 |
---|---|
& | 按位相与 |
| | 按位或 |
^ | 按位异或 |
~ | 按位取反 |
<< | 左移 |
>> | 右移 |
18、其他不常用事项
断言:assert 语句 字符串1 :如果语句正确则没事,如果语句失败则会报错并输出字符串1
使用断言函数来测试:
断言函数 意思 assertEqual(arg1,arg2,msg=) 测试arg1与arg2是否一样,如果一样则万事大吉,否则就要报错并返回指定的内容msg assertNotEqual(arg1,arg2,msg = ) 测试arg1与arg2是否不一样,如果不一样则万事大吉,否则就要报错并返回指定的内容msg sys.exc_info()可以回溯最后的异常。会返回一个三元组(type,value/message,traceback)即(异常类型,异常信息,堆栈信息)
4、sorted详解:
- 一般的使用:l=[3,2,1],sorted(l),返回的是正序的l,不会修改原来的列表。
- 特殊的使用:sorted(l,key=指定方式),例如:
- sorted(l,key=abs):利用每一个数的绝对值比较
- sorted(l,key=len):利用每一个数的长度比较
- sorted(l,key=str.lower):将每一个以小写的方式比较
Python爬虫(超全版)
0、正则总结
a、正则常用的方法:
方法 | 含义 |
---|---|
match() | 判断一个正则表达式是否从开始处匹配一个字符串 |
search() | 遍历字符串,找到正则表达式匹配的第一个位置 |
findall() | 遍历字符串,找到正则表达式匹配的所有位置,并以列表的形式返回 |
finditer() | 遍历字符串,找到正则表达式匹配的所有位置,并以迭代器的形式返回 |
sub() | sub(‘正则’,‘替换项’,待匹配) 就是将匹配到的部分,用替换项替换 |
compile |
compile(正则表达式) 将通用正则表达式转成一个正则对象,下面只需要使用这个就好。 比如a = re.compile(’\d{2}’) re.match(a,‘123你好啊’) re.match(a,‘4421我也好啊’) |
serarch 与match的区别:
有时候你可能会耍点小聪明,使用 re.match() 然后在 RE 的前边加上 .*。但尽量不要这么做,最好采用 re.search() 代替。正则表达式编译器会对 REs 做一些分析,以便可以在搜索匹配时提高速度。一般分析会先找到匹配的第一个字符是什么。举个例子,模式 Crow 必须从字符 ‘C’ 开始匹配,那么匹配引擎分析后会快速遍历字符串,然后在 ‘C’ 被找到之后才开始全部匹配。
按照上面的分析,你添加一个 .* 会导致这个优化失败,这就需要从头到尾扫描一遍,然后再回溯匹配 RE 剩余的部分。所以,请使用 re.search() 代替。
在匹配到的内容可以用一些常用方法查看一下
含义 | |
---|---|
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
m = p.match('fishc')
>>> m.group()
'fishc'
>>> m.start()
0
>>> m.end()
5
>>> m.span()
(0, 5)
b、正则常用的特殊字符
特殊字符 | 含义 |
---|---|
\d | 匹配任何十进制数字;相当于类 [0-9] |
\D | 与 \d 相反,匹配任何非十进制数字的字符;相当于类 [^0-9] |
\s | 匹配任何空白字符(包含空格、换行符、制表符等);相当于类 [ \t\n\r\f\v] |
\S | 与 \s 相反,匹配任何非空白字符;相当于类 [^ \t\n\r\f\v] |
\w | 匹配任何字母,见上方解释 |
\W | 于 \w 相反 |
\b | 匹配单词的开始或结束 |
\B | 与 \b 相反 |
c、正则常用的格式
字符 | 描述 |
---|---|
\ |
将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n “匹配字符”n "。"\n “匹配一个换行符。串行”\\ “匹配”\ “而”\( “则匹配”( "。
|
^ |
匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n “或”\r "之后的位置。
|
$ |
匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n “或”\r "之前的位置。
|
* |
匹配前面的子表达式零次或多次。例如,zo*能匹配“z “以及”zoo "。*等价于{0,}。
|
+ |
匹配前面的子表达式一次或多次。例如,“zo+ “能匹配”zo “以及”zoo ",但不能匹配"z "。+等价于{1,}。
|
? |
匹配前面的子表达式零次或一次。例如,“do(es)? “可以匹配”does “或”does “中的”do "。?等价于{0,1}。
|
{n} |
n是一个非负整数。匹配确定的n次。例如,“o{2} “不能匹配”Bob “中的”o ",但是能匹配"food "中的两个o。
|
{n,} |
n是一个非负整数。至少匹配n次。例如,“o{2,} “不能匹配”Bob “中的”o ",但能匹配"foooood “中的所有o。”o{1,} “等价于”o+ "。"o{0,} “则等价于”o* "。
|
{n,m} |
m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3} “将匹配”fooooood “中的前三个o。”o{0,1} “等价于”o? "。请注意在逗号和两个数之间不能有空格。
|
? |
当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo ","o+? “将匹配单个”o ",而"o+ “将匹配所有”o "。
|
. |
匹配除“\ n “之外的任何单个字符。要匹配包括”\ n “在内的任何字符,请使用像”(.|\n) "的模式。
|
(pattern) |
匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\( “或”\) "。
|
(?:pattern) |
匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|) “来组合一个模式的各个部分是很有用。例如”industr(?:y|ies) “就是一个比”industry|industries "更简略的表达式。
|
(?=pattern) |
正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000) “能匹配”Windows2000 “中的”Windows ",但不能匹配"Windows3.1 “中的”Windows "。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
|
(?!pattern) |
正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000) “能匹配”Windows3.1 “中的”Windows ",但不能匹配"Windows2000 “中的”Windows "。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
|
(?<=pattern) |
反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows “能匹配”2000Windows “中的”Windows ",但不能匹配"3.1Windows “中的”Windows "。
|
(?<!pattern) |
反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows “能匹配”3.1Windows “中的”Windows ",但不能匹配"2000Windows “中的”Windows "。
|
x|y |
匹配x或y。例如,“z|food “能匹配”z “或”food "。"(z|f)ood “则匹配”zood “或”food "。
|
[xyz] |
字符集合。匹配所包含的任意一个字符。例如,“[abc] “可以匹配”plain “中的”a "。
|
[^xyz] |
负值字符集合。匹配未包含的任意字符。例如,“[^abc] “可以匹配”plain “中的”p "。
|
[a-z] |
字符范围。匹配指定范围内的任意字符。例如,“[a-z] “可以匹配”a “到”z "范围内的任意小写字母字符。
|
[^a-z] |
负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z] “可以匹配任何不在”a “到”z "范围内的任意字符。
|
贪婪模式:
.*或.+这样可以一直匹配,如果后面有可以匹配的就继续往下匹配。
非贪婪模式:
.*?或.+? 这样就只匹配一次,成功就结束了
示例:
s = '<html><head><title>Title</title>'print(re.match('<.*>', s).group())>>><html><head><title>Title</title>print(re.match('<.*?>', s).group())>>><html>解析:
何为贪婪?何为不贪婪?
所谓的贪婪,指的只要还能匹配就一直往下匹配。
正如案例:re.match('<.*>', s)其实,过程是这样的,首先匹配<然后匹配.*,所谓的.*指的是匹配空格或任意字符0次或多次,并且要以>后面的字符结束。其实意思就是首先匹配html然后后面有>结束,但由于是贪婪的,所以继续往下匹配,则当前匹配的是html><head此时有>结束,但由于是贪婪地,所以继续往下匹配,直到匹配到最后的title,这个时候后面的是>,所以匹配上。此时字符串结束,所以匹配的就是<html><head><title>Title</title>。如果s = '<html><head><title>Title</title'这样的话在贪婪模式中,匹配到title时,发现后面接着的是>,则继续往下匹配,直到匹配到/title(即字符串结尾)发现后面没有跟着>,所以表示现在贪婪的是不合法的,所以回退到最近一次合法的区域,即匹配的是:<html><head><title>
非贪婪案例:re.match('<.*?>',s)其实,过程是这样的,首先匹配<,然后匹配.*?,.*?指的是匹配空格或任意字符0次或多次,并且要以>后面的字符结束。由于是非贪婪的,所以当匹配到html发现后面的是>,就结束,不会继续往下匹配了。所以匹配的是<html>
d、常用正则速查库
常用的格式 | |
---|---|
用户名 | /1{3,16}$/ |
密码 | /2{6,18}$/ |
密码2 | (?=^.{8,}KaTeX parse error: Undefined control sequence: \d at position 7: )(?=.*\̲d̲)(?=.*\W+)(?=.*… (由数字/大写字母/小写字母/标点符号组成,四种都必有,8位以上) |
十六进制值 | /^#?([a-f0-9]{6}|[a-f0-9]{3})$/ |
电子邮箱 | /^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})KaTeX parse error: Undefined control sequence: \d at position 9: / /^[a-z\̲d̲]+(\.[a-z\d]+)*…/或\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)* |
URL | /^(https??/)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?$/ 或 [a-zA-z]+://[^\s]* |
IP 地址 | /((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/ /^(???:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ 或 ((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) |
HTML 标签 | /<([a-z]+)([<]+)(?:>(.)</\1>|\s+/>)$/或<(.)(.)>.</\1>|<(.) /> |
删除代码\注释 | (?<!http:|\S)//.*$ |
匹配双字节字符(包括汉字在内) | [^\x00-\xff] |
汉字(字符) | [\u4e00-\u9fa5] |
Unicode编码中的汉字范围 | /3+$/ |
中文及全角标点符号(字符) | [\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee] |
日期(年-月-日) | (\d{4}|\d{2})-((0?([1-9]))|(1[1|2]))-((0?[1-9])|(12)|(3[0|1])) |
日期(月/日/年) | ((0?[1-9]{1})|(1[1|2]))/(0?[1-9]|([12][1-9])|(3[0|1]))/(\d{4}|\d{2}) |
时间(小时:分钟, 24小时制) | ((1|0?)[0-9]|2[0-3])?[0-5][0-9]) |
中国大陆固定电话号码 | (\d{4}-|\d{3}-)?(\d{8}|\d{7}) |
中国大陆手机号码 | 1\d{10} |
中国大陆邮政编码 | [1-9]\d{5} |
中国大陆身份证号(15位或18位) | \d{15}(\d\d[0-9xX])? |
非负整数(正整数或零) | \d+ |
正整数 | [0-9][1-9][0-9] |
负整数 | -[0-9][1-9][0-9] |
整数 | -?\d+ |
小数 | (-?\d+)(.\d+)? |
空白行 | \n\s*\r 或者 \n\n(editplus) 或者 4*\n |
QQ号码 | [1-9]\d{4,} |
不包含abc的单词 | \b((?!abc)\w)+\b |
匹配首尾空白字符 | ^\s*|\s*$ |
编辑常用 |
以下是针对特殊中文的一些替换(editplus) 5.\n [第].\n 6.\n 7\n 8. 9\n <p[^<>]>href="javascript:if(confirm(’(.?)’))window.location=’(.?)’"<span style=".["]*rgb(255,255,255)">.[<>]
[\s\S]*?
|
一、基础库urllib
方法 | 含义 | 用法 |
---|---|---|
urllib.request.urlopen(url) | 这个方法就是访问指定的url | response=urllib.request.urlopen(url)其中response是访问返回的源码,但源码不是utf-8格式的 |
response.read() | 返回读取的源码 | content = response.read(),由于response不是utf-t格式的,如果直接读取会很乱,所以一般都在读之后转码 |
response.read().decode(‘utf-8’) | 返回读取的源码的转码形式 | content=response.read().decode(‘utf-8’)。此时读取的是utf-8格式的内容。 |
response.status | 返回内容爬取是否正确,正确是200 | print(response.status) |
response.getheaders() | 返回所有的头信息 | print(response.getheaders()) |
response.getheader(name) | 返回指定的头信息 | print(response.getheader(‘Server’))这样的话,会打印指定的头信息Server |
urllib.request.Request(url) | 返回Request类型的对象 | req = urllib.request.Request(url)。这样的目的是将其封装成Request对象,可以添加一些请求的信息,比如修改User-Agent,请求字典,请求类型等。 |
urllib.request.Request(url,date={},headers=’’) | 返回Request类型的对象 | req =urllib.request.Request(url,date={},headers=’’)。这样的目的是将其封装成Request对象,可以添加一些请求的信息,比如修改User-Agent,请求字典,请求类型等,只是与之前不同的是,直接在定义的时候添加 |
req.add_信息类型(信息) | 给req添加一个请求信息 | req.add_header(‘User_Agent’,‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36’)类似这样,也就是在req的定义所需要的额外的信息没有被定义的时候添加时,就可以手动添加 |
urllib.parse.urlencode(data).encode(‘utf-8’) | 将需要发送的字典转成网页需要的utf-8格式 | date=urllib.parse.urlencode(data).encode(‘utf-8’)。这个是将所要post的字典由字典类型转成网页所需要的utf-8类型 |
案例代码展示:
翻译爬虫post
#导入三个模块,分别是:
#request模块用来访问地址
#parse模块用来将请求正文的data字典从原本形式即utf-8封装起来.
#json模块将read获得的字符串形式变成字典形式
import urllib.request
import urllib.parse
import json
#输入要翻译的文字
tarslate=input('你要翻译的是:')
#翻译的请求url(即爬虫要找到的地址)赋给url(自定义的变量)
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
#创建一个字典用来收纳请求正文的字典
data={}
#将请求正文的各个内容用字典形式保存在data 中,其中i的值要改成自定义要翻译的变量
data['action']= 'FY_BY_CLICKBUTTION'
data['client']='fanyideskweb'
data['doctype']='json'
data['from']='AUTO'
data['i']=tarslate
data['keyfrom']='fanyi.web'
data['salt']='1536061146665'
data['sign']='156a72f2e9a7e3e1dc040cce61ed7eb2'
data['smartresult']='dict'
data['to']='AUTO'
data['typoResult']='false'
data['version']='2.1'
#此时的data 字典还不能被直接访问传入,因为要求是applaction格式,需要用urllib.parse.urlencode来给他转码一下,编码形式用encode('utf-8')来封装(即将原先是utf-8形式变成一种爬虫抓取的编码形式)再重新赋给data
data=urllib.parse.urlencode(data).encode('utf-8')
#调用urllib.request.urlopen来访问地址,其中有data 表示用post形式
response=urllib.request.urlopen(url,data)
#获取后的response拥有得到的地址的操作,可以用read()来读取,此时读取的是二进制编码,需要用decode('utf-8')来解封成utf-8即原先网页显示的形式
html=response.read().decode('utf-8')
#因为是用data字典来访问获取的,得到的是一个字符串形式的字典(即json格式),不宜被用户观看,需要调用json的loads()来将它转成字典形式
target=json.loads(html)
#打印出来,即选择出字典中对应的关键字的被翻译的值所在的地方
print('结果是%s' %(target['translateResult'][0][0]['tgt']))
input('')
图片爬取爬虫,GET
import urllib.request
import os
def get_url(url):req=urllib.request.Request(url)req.add_header('User_Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36')response=urllib.request.urlopen(url)html=response.read()print(url)return html
def get_num(html):html=html.decode('utf-8')a=html.find('current-comment-page')+23b=html.find(']',a)nums=html[a:b]return nums
def get_picture(html):html=html.decode('utf-8')picture_list=[]a=html.find('img src=')print(a)while a!=-1:b=html.find('.jpg',a,a+255)print(b)if b!=-1:picture_list.append(html[a+9:b+4])else :b=a+9a=html.find('img src=',b)for each in picture_list:prinf(each)def in_file(folder,html,i):with open ('D://图片//1' %i,'wb') as f:f.write(html)def download_picture(folder='picture',page=10):os.mkdir(folder)os.chdir(folder)url='https://desk-fd.zol-img.com.cn/t_s960x600c5/g5/M00/02/0E/ChMkJ1w9tMqIEr5sABaSMmZkIzwAAuZvQHkBxMAFpJK682.jpg'html=get_url(url)this_num=int(get_num(html))for i in range(page):this_num+=ipage_url=url+'page-'+str(this_num)+'#comments'html=get_url(page_url)get_picture(html)
download_picture()
二、升级库requests库(搭配正则表达式re,与解析库Beautiful Soup4)
方法 | 含义 | 用法 |
---|---|---|
requests.get(url) | 以get的方式来访问网址 | response = requests.get(url)这将返回使用get方式获取的网址的源码 |
response.text | 返回源码的内容,正常来说是已经转码过的 | text = response.text |
requests.post(url,其他选项) | 以post的方式来访问网站 | response = requests.post(url,datas…)这个的意思是以post的形式来访问,并且附带一些要post的内容 |
response.status_code | 返回的是爬取的状态码 | 200表示成功没有出错 |
在GET和POST中,可以添加的辅助信息
params : 字典或字节序列,作为参数增加到 url 中
data : 字典、字节序列或文件对象,作为 Request 的内容
json : JSON 格式的数据,作为 Request 的内容
headers : 字典,HTTP 定制头
cookies : 字典或 CookieJar, Request 中的 cookie
auth : 元组,支持 HTTP 认证功能
files : 字典类型,传输文件
timeout : 设定超时时间,秒为单位
proxies : 字典类型,设定访问代理服务器,可以增加登录认证
allow_redirects : True/False,默认为 True,重定向开关
stream : True/False, 默认为 True, 获取内容立即下载开关
verify : True/False, 默认为 True, 认证 SSL 证书开关
cert : 本地 SSL 证书路径
使用案例GET:
import requests
url='http://www.cntour.cn/'
info=requests.get(url)
print(info.text)
使用案例POST
import requests
import json
print('输入要翻译的内容')
a=input(":")
url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
datas={'i':a,
'from':'AUTO',
'to':'AUTO',
'smartresult':'dict',
'client':'fanyideskweb',
'salt':'15437410255351',
'sign':'a65df43d575ebfebe56eed6dfba6d75e',
'ts':'1543741025535',
'bv':'37074a7035f34bfbf10d32bb8587564a',
'doctype':'json',
'version':'2.1',
'keyfrom':'fanyi.web',
'action':'FY_BY_REALTIME',
'typoResult':'false'}
#print(datas)
info=requests.post(url,datas)
print(info.text)
infos=json.loads(info.text)
print(infos)
#traslate=info['translateResult'][0][0]['tgt']
print(infos['translateResult'][0][0]['tgt'])
Beautiful Soup4的使用方法:
超全官方文档:
https://beautifulsoup.readthedocs.io/zh_CN/latest/
自己的总结:
1、首先将抓取的内容通过Beautifulsoup库实例化一个bs4对象
- soup=BeautifulSoup(markup, “html.parser”)解析网址返回信息,并选择解析器生成soup对象
- 其中,markup是爬取的内容,html.parser是使用的解析器。解析器有四种,优劣各不一样,一般就用html.parser即可
2、通过soup获取数据的方法
soup的方法 | 示例 | 含义 |
---|---|---|
soup.prettify() | soup.prettify() | 返回的是soup解析的H5格式的全内容 |
soup.标签 | soup.title | 返回的是指定标签第一个匹配项的全部内容(标签+内容) |
soup.标签.name | soup.title.name | 返回指定标签的第一个匹配项的的标签名 |
soup.标签.string | soup.title.string | 返回指定标签第一个匹配项的内容 |
soup.get_text() | soup.get_text() | 返回的是所有爬取信息的所有去标签内容 |
soup.标签[] | soup.title[id] | 返回指定标签匹配的第一个项的[]内的值,比如id class要写成class_ |
soup.find(条件) | soup.find(id=1000),条件可以是id,或者是标签名(只是标签名要用’'包起来) | 返回指定条件的第一个项的对象,接下来就可以获得name,string等 |
soup.find_all(条件) | soup.find_all(‘p’),条件可以是id,或者标签名(只是标签名要用’'包起来) | 返回的是指定条件的所有项对象,使用列表来容纳它们。 |
tag = soup.标签 | tag = soup.标签 | 返回的是第一个匹配的标签对象 |
tag.string | print(tag.string) | 返回标签对应的内容 |
tag.name | print(tag.name) | 返回的是标签对应的名字 |
tag.contents | tags = tag.contents | 返回以列表形式的子标签 |
tag.children | for i in soup.标签.children: | tag.children是一个字标签的生成器 |
BS4的案例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
import requests
import bs4
import json
import MainUtil# 相对路径,也是需要将此路径存入数据库
resources_file_path = '/resources/movie/cinemaNameList.ini'
scratch_url = 'http://theater.mtime.com/China_Beijing/'# scratch data with define url
def scratch_latest_movies(scratch_url, old_movies):data = requests.get(scratch_url).textsoup = bs4.BeautifulSoup(data, "html.parser")new_movies = []new_movies_json = json.loads(soup.find('script', text=re.compile("var hotplaySvList")).text.split("=")[1].replace(";", ""))coming_movies_data = soup.find_all('li', class_='i_wantmovie')# 上映的电影for movie in new_movies_json:move_name = movie['Title']if move_name not in old_movies:new_movies.append(movie['Title'])# 即将上映的电影for coming_movie in coming_movies_data:coming_movie_name = coming_movie.h3.a.textif coming_movie_name not in old_movies and coming_movie_name not in new_movies:new_movies.append(coming_movie_name)return new_moviesif __name__ == '__main__':MainUtil.main(resources_file_path, scratch_url, scratch_latest_movies)
三、Scrapy爬虫框架(爬虫精华)
1、框架图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tHZB0tze-1571807652563)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1566529988711.png)]
2、框架图个人总结:
- 此框架总共分为五部分
- 第一部分Scheduler(调度器)。所谓Scheduler作用是对多个爬虫请求的request进行调度,即哪个先去访问,哪个后访问,是个队列。
- 第二部分Scrapy Engine(Scrapy引擎)。所谓Scrapy引擎,就是用来协调Scrapy各个组件。比如,把爬虫的请求发给调度器,把调取器选出的要先访问的请求发给Downloader下载器。把爬虫处理的item返给管道Pipeline。
- 第三部分Downloader(下载器)。所谓Downloader下载器,就是处理Scheduler调度器返回的访问请求,将它与网站相交互,返回一个response,response包含了爬取的所有的信息
- 最核心的部分Spiders(爬虫)。所谓的Spiders就是写代码进行如何爬取,然后爬取的数据如何处理,以及如何继续爬取。
- Item Pipeline(管道)。所谓的Pipeline管道,就是将爬虫封装成item的数据进行管理,即是存入文件还是数据库什么的。
- 附加的部分
- Downloader Middlewares(下载中间件)。所谓的下载中间件就是在将请求发送给Downloaders下载器之前,给这些请求添加辅助信息,比如代理信息,更换User-Agent信息等
- Spider Middlewares(爬虫中间件)。所谓的爬虫中间件就是在返回给爬虫的response时,首先通过中间件,对response进行处理。
3、Scrapy 框架的案例:
Python进阶篇
一、生成器,推导式,迭代器,闭包,装饰器,描述符
迭代器:所谓迭代器就是能自动的返回下一项的序列。即能够通过next来调用下一个元素。比如常见的list,tuple等。一般来说用for 就可以触发next函数
推导式:
- 列表推导式:比如:[i的表达式 for i in 范围 if i要满足的条件]
- 字典推导式:比如:{key:value for k与v的循环 if判断k与v}
- 集合推导式: 比如:{x**2 for x in [1, 1, 2]}
生成器:所谓生成器就是避免一次性产生待使用的所有的元素(推导式是一次性生成所有元素),而是每一次调用生成一次。
- 比如: g = (x * x for x in range(10))
- 则g是一个生成器,初始时没有元素,调用g.next()时生成下一个元素。
描述符:x = property(方法一,方法二,方法三)
则 对象.x调用方法一;对象.x = 值调用方法二;del 对象.x 调用 方法三
示例: class A:def __init__(self,num):self.num = numdef get(self):return self.numdef set(self,new_num):self.num = new_numdef dels(self):del self.numx = property(self.get,self.set,self.dels)
闭包:
何为闭包?答:闭包就是外函数调用内函数并返回内函数的函数名,内函数使用外函数的变量,返回执行结果
比如:
def A():a = 1def B():b = a+1return breturn B
闭包的特点是:1、内函数不能修改外函数的变量,除非在内函 数中声明了nonlocal 变量,这样才能修改外 变量(类似于全局与局部,但有一点不同)
2、外函数返回的是内函数的名字,当外函数被 删除时,内函数的其实并没有被删除, 仍 可以使用,只是在删外函数之前要赋一个指 向内函数的引用,这也就是为什么外函数返 回的是内函数的函数名(也就是引用指针) 方便之后再引用。
装饰器:
何为装饰器?答:装饰器就是在使用某函数之前先执行另一个 函数。
示例:
import time as t def decorator(fun):def wrapper(*args,**kwargs):y=fun(*args)print(y)return wrapper @decorator def myfun(x,y):x+=yreturn x myfun(1,2)
装饰器的通用模板是:
def fun_o(fun_i):def wrapper(*args,**kwargs):函数体fun_i(*args)return wrapper@fun_0 def fun_i(参数1,参数2...):函数体fun_i(参数1,参数2...)
装饰器通用模板的使用说明
首先解释*args与**kwargs *args是指的是传入的多个变量组成的元组 比如: def a(*arg):print(arg) a(1,2,3,4) 则打印:(1,2,3,4) 而**kwargs指的是传入的多个赋值类型的变量组成的字典 比如: def a(**kwarg):print(kwarg) a(a=1,b=2,c=3) 则打印:{'a': 1, 'b': 2, 'c': 3}如果*arg与**kwargs同时使用: 比如: def a(*arg,**kwargs):print(arg)print(kwargs) a(1,2,3,a=4,b=5) 则打印: (1, 2, 3) {'a': 4, 'b': 5} 即对应的添加入对应的元组或字典中。到这开始解释装饰器: def fun_o(fun_i):def wrapper(*args,**kwargs):函数体fun_i(*args,**kwargs)return wrapper@fun_0 def fun_i(参数1,参数2...):函数体fun_i(参数1,参数2...)当调用fun_i时,首先调用它的装饰器方法fun_0。 先把调用的方法名fun_i作为参数传入装饰器方法fun_o中,然后return wrapper。 return 回来的wrapper后面紧跟着(参数1,参数2...)接着调用wrapper方法。将对应参数传入args与kwargs中。执行对应的函数体。然后调用原方法fun_i(*args,**kwargs)。此时就是调用它,执行它的方法体,这个时候就不会使用装饰器了。
装饰器进阶(多个装饰器):
def a(b):def swapper(*args,**kwargs):print('a')b(*args,**kwargs)return swapperdef c(b):def swapper(*args,**kwargs):print('c')b(*args,**kwargs)return swapper@a @c def b(*args,**kwargs):print('b')>>> b(1,2,3) a c b 这个的逻辑是,首先将b作为装饰器参数传给装饰器方法,然后return c的swapper,然后运行swapper(1,2,3),此时将c的swapper作为参数传给装饰器方法a,然后return a的swapper。此时执行a的swapper(1,2,3) 打印a 然后执行a的swapper内的b,而此时的b是由c的swapper传递过来,所以执行c的swapper方法 打印c 然后执行c的swapper内的b,此时的b是方法b,所以 打印b 最后的结果为 a c b
二、元类与抽象基类
元类
元类就是创建类的类,在python中,一切皆对象,所以class 创建的类本质上也是一个对象。而用来创建类的类时type
type动态创建类的方法:
type(类名,(父类的元组),{属性或方法的字典})
Foo = type('Foo', (), {'bar':True,'fun1':fun1}) 其中方法fun1在外部定义好的,并且有参数self
使用元类的操作
就是通过一个类的__new__方法,来返回指定需要的类
在这里__metaclass__是指定用什么来创建类,如果没有metaclass 默认就是元类type。
class UpperAttrMetaClass(type):# __new__ 是在__init__之前被调用的特殊方法# __new__是用来创建对象并返回之的方法# 而__init__只是用来将传入的参数初始化给对象# 你很少用到__new__,除非你希望能够控制对象的创建# 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__# 如果你希望的话,你也可以在__init__中做些事情# 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用def __new__(cls, future_class_name, future_class_parents, future_class_attr):#遍历属性字典,把不是__开头的属性名字变为大写newAttr = {}for name,value in future_class_attr.items():if not name.startswith("__"):newAttr[name.upper()] = value# 方法1:通过'type'来做类对象的创建return type(future_class_name, future_class_parents, newAttr)# 方法2:复用type.__new__方法# 这就是基本的OOP编程,没什么魔法#python2的用法 class Foo(object):__metaclass__ = UpperAttrMetaClassbar = 'bip'# python3的用法 # class Foo(object, metaclass = UpperAttrMetaClass): # bar = 'bip'print(hasattr(Foo, 'bar')) # 输出: False print(hasattr(Foo, 'BAR')) # 输出:Truef = Foo() print(f.BAR) # 输出:'bip'
抽象基类
所谓的抽象基类就是类不能被实例化,其中的方法是抽象方法或普通方法
定义抽象基类的步骤:
导入用来定义抽象类的基类abc
定义基类,继承抽象基类abc.ABCMeta
定义抽象方法:@abc.abstractmethod
def 方法
定义子类来继承这个基类并重写其方法:
import abc class Human(metaclass=abc.ABCMeta):@abc.abstractmethod # 规定子类必须有名为introduce的实例方法def introduce(self):pass@abc.abstractproperty # 规定子类必须有名为country的装饰器方法def country(self):pass@abc.abstractclassmethod # 规定子类必须有名为gender的类方法def gender(cls):pass@abc.abstractstaticmethod # 规定子类必须有名为hello的静态方法def hello():pass class Person(Human):__country = "China"def __init__(self, name, age):self.name = nameself.age = agedef introduce(self):return "I'm {}, {}.".format(self.name, self.age)#@property是将一个方法变成一个属性的装饰器@propertydef country(self):return Person.__country@classmethoddef gender(cls):return "female"@staticmethoddef hello():print("What the hell?")person = Person("Li", 24) print(person.introduce()) print(person.country) print(Person.gender()) person.hello()# I'm Li, 24. # China # female # What the hell?
二、设计模式
简单工厂模式:
定义:所谓简单工厂模式就是创建一个基本的接口类,其 中包含一个没有方法体的方法。然后创建接口类的子类。 重写其方法。这个方法的作用是根据传入的参数来创建对 应的实例化对象。优点在于:使用工厂来实例化对象,根 据传入的不同参数创建不同的对象,封装了对对象的实例 化过程,减少了耦合性。缺点是当修改子类的定义时,需 要修改工厂类的内容,比如参数个数等。
例子:
#定义一个接口的抽象类 class org_class():def get_class(self):pass #继承这个接口类定义一个简单工厂类 class factor(org_class): #根据传入的不同的参数,返回不同的实例化对象def get_class(self,name):if name=='奔驰':return Mercedes_Ben()if name=='宝马':return BWM()if name=='大众':return Volkswagen() #定义各个具体子类 class Mercedes_Ben():def get_name(self):return '这是奔驰' class BWM():'''def __init__(self,name):self.name=name #当这样时,会导致工厂的实例化缺少参数,因此必须修改工厂类的实例化内容'''def get_name(self):return '这是宝马' class Volkswagen():def get_name(self):return '这是大众' #实例化工厂类对象 fac=factor() #根据工厂实例化对象,传入不同的参数创建不同的对象,封装了对象的实例化过程,减少了耦合度 car1=fac.get_class('奔驰') print(car1.get_name()) car2=fac.get_class('大众') print(car2.get_name()) car3=fac.get_class('宝马') print(car3.get_name()) #缺点是当修改子类的定义时需要修改工厂类的内容''' 解析: 定义一个接口类,其方法是一个没有方法体的方法。 创建一个工厂类,继承接口类,并重写那个没有方法体的方法。 这个方法的作用是:根据输入的参数,来选择性的实例化一个对应的对象,并返回。 如上面代码,创建三个需要的车类,然后创建一个工厂类,重写工厂类的方法,使得,只需要实例化一个工厂类,然后根据调用工厂方法传的参数的不同返回不同的实例化对象。 比如,想要实例化一个宝马车对象,只需要将宝马字段,作为参数调用工厂对象的get_class方法,这样在get_class方法中,根据if语句,来判断要返回哪个对象。本质上就是使用统一的方法进行实例化所需要的对象,而不用知道具体的类的名字是什么。更加安全与减少代码耦合性。 缺点就是一旦需要实例化的类一修改定义,则工厂类的方法就需要修改。 '''
工厂方法模式:
定义:所谓的工厂方法模式,就是将使用方法来实例化这些 类,只是为了避免简单工厂的修改问题,所以给每一个要实 例化的类都创建一个子工厂,就是工厂方法是用来实例化子 工厂的。
例子:
#定义子工厂的抽象类接口 class son_fac():def get_class(self):pass #定义各个具体子类 class Mercedes_Ben():def get_name(self):return '这是奔驰' class BWM(): #当修改类时,只需要修改子工厂的即可,不会影响工厂方法生成对象'''def __init__(self,name):self.name=name'''def get_name(self):return '这是宝马' class Volkswagen():def get_name(self):return '这是大众' #定义子工厂 class factor_MB(son_fac):def get_class(self):return Mercedes_Ben() class factor_BWM(son_fac):def get_class(self):return BWM() #这是在修改类时修改的子工厂的地方 # return BWM('宝马') class factor_Volk(son_fac):def get_class(self):return Volkswagen() #定义工厂方法 def factor(name):if name=='奔驰':return factor_MB()if name=='宝马':return factor_BWM()if name=='大众':return factor_Volk() name=input('请输入你要实例化的对象的名字:') #子工厂1 fac=factor(name) car1=fac.get_class() print(car1.get_name()) name=input('请输入你要实例化的对象的名字:') #子工厂1 fac=factor(name) car1=fac.get_class() print(car1.get_name()) name=input('请输入你要实例化的对象的名字:') #子工厂1 fac=factor(name) car2=fac.get_class() print(car2.get_name())''' 解析: 此模式是将想要生成的类都定义其对应的工厂类,工厂类有一个实例化需要类的方法。 工厂方法就是根据传的参数,实例化对应的工厂类,然后工厂类再调用其方法实例化所需要的真正的类的对象。在这里来说,给每个车对应其工厂类,然后根据参数的不同,在工厂方法中实例化对应的工厂类的对象,然后通过这个对象调用其方法,实例化所需要的真正的类的对象。这种模式的优点是能够避免代码耦合性,并且如果需要修改,工厂方法不需要修改,只需要修改对应的工厂类即可。'''
抽象工厂模式:
定义:所谓抽象工厂模式,就是将需要实例化的类进行分类。 具体分类的方式,是通过创建多种对应基类,继承对应 的基类。然后子工厂也不止一个,即每一种分类对应一 个子工厂,每个子工厂继承一个子工厂基类。然后工厂 类或方法通过传入的参数的不同,实例化不同种类的子 工厂对象,然后调用子工厂对象的方法,根据参数,实 例化对应当前分类的子分类对象,即需要的对象。
#定义实现类的抽象接口 class color_org_class():def get_color(self):pass class shape_org_class():def get_shape(self):pass #继承接口实现真正的类(圆形,正方形,三角形;红色,蓝色,黄色) class circle(shape_org_class):def get_shape(self):return '这是圆形' class square(shape_org_class):def get_shape(self):return '这是正方形' class Triangle(shape_org_class):def get_shape(self):return '这是三角形' class Red(color_org_class):def get_color(self):return '这是红色' class Bule(color_org_class):def get_color(self):return '这是蓝色' class Yellow(color_org_class):def get_color(self):return '这是黄色' #定义子工厂的抽象类接口 class son_fac():def get_shape_class(self):passdef get_color_class(self):pass class get_shape_fac(son_fac):def get_shape_class(self,name):if name=='圆形':return circle()if name=='正方形':return square()if name=='三角形':return Triangle() class get_color_fac(son_fac):def get_color_class(self,name):if name=='红色':return Red()if name=='蓝色':return Blue()if name=='黄色':return Yellow() def factor(name):if name=='图形类':return get_shape_fac()if name=='颜色类':return get_color_fac() if __name__=='__main__':content=input('请输入想要创建的类的种类(图形类,还是颜色类:)')if content=='图形类':fac=factor(content)types=input('请输入要创建的图形种类:')graphics=fac.get_shape_class(types)print(graphics.get_shape())else:fac=factor(content)types=input('请输入要创建的颜色种类:')colors=fac.get_color_class(types)print(colors.get_color())''' 首先,有两种大类,一种是图形类,一种是颜色类。创建其对应的图形基类与颜色基类。在创建图形类与颜色类时对应继承者这两个基类。 然后创建一个子工厂基类。接着创建继承子工厂基类的多个子工厂类。上面例子,就是创建一个继承子工厂基类的图形子工厂类与一个继承子工厂基类的颜色子工厂类。 在每一个子工厂类里面有一个创建本大类的小类的方法,比如在图形类子工厂中,有一个方法def get_shape_class,这就是创建正方形小类,三角形小类,圆形小类。 然后创建一个总的工厂类(需要继承总工厂类基类)或方法。然后通过传入的大类的不同实例化子工厂类,然后通过子工厂对象的方法,根据参数实例化小类的对象。其实就是工厂类里有多个方法来创建多个子工厂类对象,每个子工厂类里有创建对应小的,要求的分类的实例化对象。优点在于:在工厂方法的优点基础上,可以对不同分类的产品进行整体约束。缺点是当需要修改一个类别是,需要修改对应的子工厂类。'''
以上的所有都是工厂模式,多个工厂模式之间在需求变幻时,可能会发生相互转换,本质上都是为了解决耦合问题。
单例模式:
定义:所谓单例模式,就是只创建一个类的实例,其他创建的实 例都是对第一个实例的引用,不占用内存,效率较高。
#创建一个单例模式的类 class Class_Solen(object): #创建魔法属性,即类属性,用来标识这个类是否被实例化过一次_obj=None #创建一个魔法属性,即类属性,用来标识是否被实例化过一次_init=True #实例化类,如果没实例化过则实例化,如果实例化过就直接用if跳过def __init__(self,name):if Class_Solen._init:self.name=nameClass_Solen._init=False #利用__new__魔法方法,来进行只实例化一次,其余的都是引用。def __new__(cls,*args,**kwargs): #如果没实例化则调用父类方法实例化并赋给类属性,来让下一次实例化时返回的不是新的实例化对象 #而是第一个实例化对象的指针if not cls._obj:cls._obj=super().__new__(cls)return cls._obj#创建两个实例化对象进行测试,结果a与b的id号一致,且a与b的name属性都是haha 因为是同一个对象的两个#指针而已,且第一次即a在实例化时只调用一次init初始化属性 a=Class_Solen('haha') print(a.name) b=Class_Solen('lala') print(b.name) print(a.name) 结果: haha haha haha >>> a is b True解析: 在本模式中,在第一次实例化时,调用Class_Solen的__new__方法,此时类属性_obj是空,所以通过object的__new__方法实例化一个Class_Solen对象返回,然后返回cls._obj。接着回到Class_Solen的__init__方法,对其进行初始化,初始化的是cls._obj指向的Class_Solen对象。然后判断_init,当第一次实例化时_init是True否则为False。 接下来实例化b,首先调用__new__发现已经实例化了,然后返回一个指针cls._obj,接着进行__init__发现_init已经为False了表名已经实例化一次了,就跳过不实例化。这样就保证了只有一个实例化对象,其他都是指针。为什么有_init这个类变量呢? 主要在于__new__与__init__这两个底层的实现。 首先一个类要被实例化,首先调用其__new__,然后返回指定实例化对象,这个对象可能是别的类的。如果是本类的对象,就调用本类的__init__方法对其实例化。如果是其他类的对象,就调用对应的__init__。 有_init的原因是,第一次调用返回的是Class_Solen对象,虽然是_obj来指向,但是只要是本类的对象,并第一次调用就要实例化。第二次实例化Class_Solen时,由于是已经实例化了,所以跳过实例化,返回_obj指向的对象的指针,但接下来调用__init__时,由于是本类的对象所以仍需实例化,但当前不想实例化,所以需要一个类属性来跳过实例化。 即实例化一个对象必须执行__new__与__init__方法,只是执行谁的__init__不一定。
适配器模式:
二、python连接数据库
python连接oracle
包是:cx_Oracle
python连接mysql
包是:pymsql
用法:无论是oracle还是mysql,所有的操作步骤都是一样的
import pymsql/cx_Oracle #第一步,连接数据库 #oracle: db=cx_oracle.connect('用户名/密码@主机名/数据库') #mysql db=pymysql.connect("主机名","用户名","密码","表" ) #第二步,获取游标 cursor = db.cursor() #第三步,创建sql语句 sql = ' ' #第四步,执行sql语句 cursor.excute(sql) #第五步,获得数据 data = cursor.fetchone() #获得一行数据 data = cursor.fetchall() #获得所有数据 #第六步,如果不是查询就直接到第六步,没有第五步 db.commit() db.rollback()#第七步,结束 #关闭游标 cursor.close() #关闭数据库 db.close()
Python数据分析篇
一、Numpy(数据处理)
常用方法
方法 示例 含义 np.array([[],[]]) a = np.array([[1,2,3],[4,5,6]]) 创建ndarry对象,并赋初值 a.shape a.shape 返回ndarry的维度,即几行几列 a.dtype a.dtype 返回ndarry的元素类型 np.zeros() b = np.zeros((5,5),dtype=np.int) 创建一个全0的,指定行数与列数。默认是float类型,所以改成int np.ones() c = np.ones((5,5),dtype=np.int) 创建一个全1的,指定行数与列数。默认是float类型,所已改成Int np.asarray() d = np.asarray(已有数组,dtype=) 从已有数组中创建ndarray对象,已有数组可以是列表,元组等。 np.arange() e = np.arrange(起始值,终止值,步长) 生成从起始值开始到终止值(但不包括终止值),步长为指定步长的ndarray对象 np.shape = x,y np.shape = 3,4 将原来的ndarray转成指定格式的ndarray对象,修改的是原对象 np.reshape((x,y)) l = np.reshape((3,4)) 生成一个将原ndarray改变指定行列格式的ndarray对象,原ndarray不变 np.linspace() f = np.linspace(起始值,终止值,num=个数) 生成从起始值到终止值(包含终止值),个数为指定个数的等差ndarray对象,默认为float型。 np.logspace() g = np.logspace(起始值,终止值,num=个数) 生成从起始值到终止值(包含终止值),个数为指定个数的的等比ndarray对象,默认为float对象。 a[1:] a[1:] 返回的是矩阵中,下标为1的那一行开始的所有行,返回的是一个ndarray对象 a[:5] a[:5] 返回的是从下标为0行的到第5行(包括第5行)的所有行 a[1:,:3] a[1:,:3] 返回的是行数为从第一行开始的所有,以及从第0列到第3列的所有列。 a[x,y] a[1,2] 返回的是下标为1的行,下标为2的列的那个值。其中:表示之后或之前所有 a[[1,2,3],[3,5,6]] a[[1,2,3],[3,5,6]] 返回的是指定行指定列的值。此为行下标为1,2,3以及列下标为3,5,6的所有值 n1±/*n2 n1±*/n2 两个ndarray相±/是将对应的值进行±/ np.dot(a,b) np.dot(a,b) 返回两个ndarray对象点积的新ndarray对象 np.sort(n1,axis,kind,order) np.sort(n1,axis = 1) 将原来的ndarray对象进行排序,n1为待排的ndarray对象,axis为排列的轴,1为行,2为列,kind是排序方法,order是待排的对象 精华版总结(重点)
创建ndarray对象
- 一维的:
np.array([1, 2, 3])
- 二维的:
np.array([(1, 2, 3), (4, 5, 6)])
- 全0的二维:
np.zeros([3,3])
- 全1的二维:
np.ones([3,3])
- 一维等差数组:
np.arange(5)
- 二维等差矩阵:
np.arange(6).reshape(2, 3)
- 创建单位矩阵(二维数组):
np.eye(3)
- 创建等差间隔一维数组:
np.linspace(1, 10, num=6)
- 创建二维随机矩阵:
np.random.rand(2, 3)
- 创建二维随机整数矩阵(数值小于 5):
np.random.randint(5, size=(2, 3))
- 依据自定义函数创建矩阵:
np.fromfunction(lambda i, j: i + j, (3, 3))
- 一维的:
ndarray普通运算
首先:
A = np.array([[1,2],[3,4] ]) B = np.array([[5,6],[7,8] ])
- 矩阵加法(对应下标元素相加):
A + B
- 矩阵减法(对应下标元素相减):
A - B
- 矩阵乘法(对应下标元素相乘):
A * B
- 矩阵除法(对应下标元素相除):
A / B
- 矩阵相乘(矩阵的点乘):np.dot(A,B)
- 数乘矩阵(矩阵的每个值乘数字):
2 * A
- 矩阵的转置:
A.T
- 矩阵求逆:
np.linalg.inv(A)
- 矩阵加法(对应下标元素相加):
数据函数
- 三角函数:
np.sin(A)
- 以自然对数函数为底数的指数函数:
np.exp(A)
- 数组的方根运算(开平方):
np.sqrt(A)
- 三角函数:
数组切片和索引:
一维数组索引:A[n]
A=np.array([1,2,3,4]) print(A[0],A[1]) 则A[n]表示下标为n的值
一维数组切片:A[m:n]
A=np.array([1,2,3,4]) print(A[0:2]) 输出:array([1, 2])则A[m:n]表示的是下标从m到n且不包括n
二维数组索引与切片:B[n],B[m:n],B[m,n],B[m:n,k],B[m:n,i:j]
B[:,k],B[[m,n],],B[[m,n],[i,j]]
其实就是灵活运用,就只有B[[m,n],[i,j]]不能用
B=np.array([[1,2,3],[4,5,6],[7,8,9]]) B[0],B[1]输出:(array([1, 2, 3]), array([4, 5, 6])) 则B[n]表示下标为n的那一行B[0:3] 输出 array([[1, 2, 3],[4, 5, 6],[7, 8, 9]]) 则B[m:n]表示下标为m到n不包括n的所有行B[0:3,2] 输出: array([3, 6, 9]) 则B[m:n,k]表示下标为m到n不包括n的行,列为k。形成的是一维B[0:3,0:2] 输出: array([[1, 2],[4, 5],[7, 8]]) 则B[m:n,i:j]表示下标为m到n不包括n的行,列为从i到j不包括j的二维矩阵。B[:,2] 输出: array([3, 6, 9]) 则B[:,k]表示第k列,不管行B[[0,1],] 输出: array([[1, 2, 3],[4, 5, 6]]) 即B[m:n,]是求的第m到n行,不包括n。不管列B[[0,1],[1,2]] 输出: array([2, 6]) 则B[[m,n],[i,j]]达不到目标效果。 返回的会是对角线
数据形状、排序操作
数组形状操作
本次:
A=np.array([[1,2,3],[4,5,6],[7,8,9]])
返回数组的行数与列数:
A.shape
更改数组形状(不改变原始数组):
B=A.reshape(2, 3)
更改数组形状(改变原始数组):
A.resize(1,6)
返回展平数组(不改变原始数组):
A.ravel()
垂直拼合数组(不改变原始数组):
C=np.vstack((A, B))
水平拼合数组(不改变原始数组):
C=np.hstack((A,B))
垂直拆分数组(不改变原始数组):
C=np.hsplit(A,3)
其中3是平均分成3份
水平拆分数组(不改变原始数组):
C=np.vsplit(A,3)
其中3是平均分成3份
数组排序取值操作
数组返回每列最大值:
np.max(A,axis=0)
数组返回每行最大值:
np.max(A,axis=1)
数组返回每列最小值:
np.min(A,axis=0)
数组返回每行最大值:
np.min(A,axis=1)
返回每列最大值索引:
np.argmax(A,axis=0)
返回每行最大值索引:
np.argmax(A,axis=1)
返回每列最小值索引:
np.argmmin(A,axis=0)
返回每行最小值索引:
np.argmin(A,axis=1)
即axis=1为行,axis=0为列
统计数组每列/行中位数:
np.median(a,axis=0/1)
统计每列/行的算数平均值
np.mean(A,axis=0/1)
统计每列/行的加权平均值
np.average(A,axis=0/1)
统计每列/行的方差
np.var(A,axis=0/1)
统计每列/行的标准差
np.std(A,axis=0/1)
数据文件操作
数据存储操作
np.savetxt(frame, array, fmt='%.18e', delimiter=None)其中frame:存到的地址array:要存的数据fmt:写入文件的格式,可以是%ddelimiter:分割字符串的方式,默认是空格(但存入csv是建议改成,)注意:CSV只能有效存储一维和二维数组 np.savetxt(), np.loadtxt()只能有效存取一维和二维数组
数据读取操作
np.loadtxt(frame, dtype=np.float, delimiter=None,unpack=False,skiprows=2)其中frame:要读取的文件dtype:读取的格式delimiter:分割字符串的方式,默认是空格(用csv建议是,)unpack:默认是False,如果是True则读入属性分别写入不同的变量skiprows:跳过最一开始几行读取注意: CSV只能有效存储一维和二维数组 np.savetxt(), np.loadtxt()只能有效存取一维和二维数组
数据存储与读取的便捷方式:
数据便捷存取(保留原格式存取一般为.npy文件)
np.save(fname,array)
数据便捷读取(保留原格式读取)
np.load(frame)
二、Pandas(数据处理)
DataFrame(表格)
方法 | 示例 | 含义 |
---|---|---|
pd.DateFrame(data,index,columns,dtype) | df = pd.DateFrame([[1,2,3],[4,5,6]],index = [‘id’,‘class’],columns = [‘小明’,‘小李’,‘小花’]) | 使用指定数据创建dataframe对象,其中data是数据,可以是ndarray对象,也可以是指定列表,也可以是指定的字典,那样的话字典的键就是指定的列索引,index是指定行索引,columns是指定列索引,dtype是指定的类型比如float |
pd.read_csv(文件名,index,columns) | pd.read_csv(‘1.csv’,index=[],columns=[]) | 从.csv文件中读取数据,重新指定行与列索引 |
df.loc[指定行索引] | df.iloc[‘小李’] | 获得指定的行,变成series对象 |
df.iloc[行下标] | df.iloc[2] | 获得行下标为2的行,变成series对象 |
df.iloc[m:n] | df.iloc[3:6] | 获得指定行下标范围的行,比如3到6行(包括第6行) |
df.drop(行) | df.drop(3) | 删除指定的行,比如下标为3的行 |
df.append(一个df对象) | df.append(df2) | 添加df2到df中 |
df.axes | df.axes | 返回df的属性,包括行的索引值 |
df.empty | df.empty | 判断是否为空 |
df.values | df.values | 返回所有的值 |
df.index | df.index | 返回所有的行索引 |
df.columns | df.columns | 返回所有的列索引 |
df.head() | df.head() | 返回前5行 |
df.tail() | df.tail() | 返回后五行 |
df.shape | df.shape | 返回行数与列数维度 |
df.describe() | df.describe() | 返回df的描述信息 |
df.sum() | df.sum() | 返回所有值的和 |
df[[列索引1,列索引2]] | df[[‘name’,‘age’]] | 返回指定列的索引 |
df[m:n] | df[3:6] | 返回下标为3到6(包括6)的列索引 |
df.loc[行索引,列索引] | df.loc[[‘小李’,‘小傻子’],[‘name’,‘age’]] | 返回行索引是小李,小傻子和列式name和age的数据 |
Series(一列数据)
方法 | 示例 | 含义 |
---|---|---|
pd.Series([],index,columns) | se = pd.Series([1,2,3],index=[‘id1’,‘id2’,‘id3’],colums = [‘age’]) | 创建series对象,其中,数据是一维的,index是行索引,columns是列索引 |
se.axes | se.axes | 返回行轴标签列表。 |
se.dtype | se.dtype | 返回对象的类型 |
se.head() | se.head() | 返回前5行 |
se.tail() | se.tail() | 返回后五行s |
se.data | se.data | 返回值 |
se.index | se.index | 返回行索引 |
se.columns | se.colums | 返回列索引 |
Pandas精华总结(重点)
一、Series操作
概念:所谓Series就是多行一列的表格,有行索引。并且索引默认是0,1,2…等。同时也有下标,下标不会改变,是0,1,2…
创建Series
从列表创建
arr = [0,1,2,3,4] s1 = pd.Series(arr)即创建列表list1 从列表中创建Series #如果要在创建时自定义索引则: index = ['a','b','c','d','e'] s1 = pd.Series(arr,index=index)
从Ndarray创建
n = np.array([1,2,3,4,5]) index = ['a','b','c','d','e'] s2 = pd.Series(n,index=index) #默认索引是0,1,2,3... #手动添加索引
从字典创建
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} s3 = pd.Series(d) s3 #则键就是索引,值就是值
修改Series索引
整体修改索引
s1.index = ['A','B','C','D','E'] #即直接s1.index=新索引即可
Series拼接
s4 = s3.append(s1) 结果: a 1 b 2 c 3 d 4 e 5 A 0 B 1 C 2 D 3 E 4 dtype: int64
修改Series
查找
s1['A'] #即按照索引即可查找 s1[0] #同时也支持按照下标索引
切片查找
s1[:3] #即Series也可以按照下标批量切片读 s1[m:n]
删除
s1=s1.drop('e') #Series对象.drop(索引)即可删除 #只是很特殊在于drop不会修改原来的只能返回修改过的
修改
s1['A']=4 #直接根据索引修改 s1[0]=22 #按照下标修改
Series运算
两个Series相加
s1.add(s2) #有相同的索引相加 #其他不是相同索引的变成NaN 比如: s1 = pd.Series([1,2,3],index=['a','b','c']) s2 = pd.Series([1,2,3],index=['a','c','d']) s1.add(s2)a 2.0 b NaN c 5.0 d NaN dtype: float64对s1与s2没影响,返回的值中,相同的相+,不同的都置为空
两个Series相减
s4.sub(s3) #有相同的索引相减 #其他不是相同索引的置为NaN 比如: A NaN B NaN C NaN D NaN E NaN a NaN b 0.0 c 0.0 d 0.0 e NaN dtype: float64
两个Series相乘
s4.mul(s3) #有相同的索引相乘 #其他不是相同索引的置为NaNA NaN B NaN C NaN D NaN E NaN a NaN b 4.0 c 9.0 d 16.0 e NaN dtype: float64
两个Series相除`
s4.div(s3) #有相同的索引相乘 #其他不是相同索引的置为NaN A NaN B NaN C NaN D NaN E NaN a NaN b 1.0 c 1.0 d 1.0 e NaN dtype: float64
Series数值获取
Series获取中位数:
s1.min()
Series求和:
s1.sum()
Series求最大值:
s1.max()
Series求最小值:
s1.min()
二、DataFrame数据类型(表格数据)
特点是:每一列的数据不一定一样,但同一列的数据一样的表格数据,有行索引也有列索引
创建DataFrame对象
方法一:使用pd.DataFrame普通方法:
dates = pd.date_range('today',periods=6) num_arr = np.random.randn(6,4) columns = ['A','B','C','D'] df1=pd.DataFrame(num_arr,index=index,columns=columns) #其中,pd.date_range()表示的是从一个时间开始生成几个时间类型数据,在这里指的是从今天开始,生成6个数据 #num_arr是ndarray对象,矩阵是6行4列 #columns是列索引 #创建df1,数据是num_arr,行索引是时间dates,列索引是columns
方法二:使用pd.DataFrame字典方法:``
data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3], 'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1],'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']} labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] df2 = pd.DataFrame(data, index=labels) df2#即使用字典创建每一列的列名和对应的值,然后生成一个行索引列表。最后生成DataFrame #如:data是每一列的列名和对应的值的字典,labels是行索引列表 #df2是根据这两个生成的DataFrame对象
从文件中读取:
- CSV读取:
df_animal = pd.read_csv('animal.csv')
- Excel读取:
pd.read_excel('animal.xlsx', 'Sheet1', index_col=None, na_values=['NA'])
- CSV读取:
DataFrame的属性操作
- 返回每一列的类名和数据类型:
df2.dtypes
- 返回每一列的类名和数据类型:
DataFrame基本操作
- 获得前n行(默认5行):
df.head(n)
- 获得后n行(默认5行):
df.tail(n)
- 获得行索引:
df.index
- 获得列索引:
df.columns
- 获得数值:
df.values
- 获得统计数据(这个统计数据指的是那些类型是数值的列。其中显示个数,中位数,平均值):
df.describe()
- 获得转置后的df对象:
df.T
- 对df对象按照某列排序:
df.sort_values(by=列名)
- 获得前n行(默认5行):
DataFrame获取数据
获取某列或某些列(以下标方式)
- 获得某列:
df[m]
- 获得某些(以切片的方式):
df[m:n]
- 获得某列:
获取某列或某些列(以列索引)
获得某列:
df[列索引名]
例如:
df['age']
获得多列:
df[[列名1,列名2,列名3]]
列如:
df2[['age','animal']]
总结:获取某列或某些列时:如果是使用下标时,则只能获得某列或用切片获得某些列。
如果是使用索引,则只能获得某一列或使用[]形式,获得某些列。
获得某些行(以下标方式):
- 获得某行:
df.iloc[m]
- 获得某些(以切片):
df.iloc[m:n]
- 获得某些(以列表[]形式):
df.iloc[[m,n,c]]
- 获得某行:
获得某些行(以索引的方式):
- 获得某行:
df.loc[索引名]
- 获得某些行:``df.loc[[索引名1,索引名2]]`
- 获得某行:
获得某行某列:
- 按下标m行n列:
df3.iat[m, n]
- 按索引 行索引列索引:
df3.loc['f', 'age']
- 按下标m行n列:
DataFrame的数值操作:
- 求平均值(默认去除那些空值):
df.mean()
- 求某列总和(默认去除那些空值):
df[列名].sum()
- 求平均值(默认去除那些空值):
DataFrame字符串处理:
- 某列转成大写:
df[列名].str.upper()
- 某列转成小写:
df[列名].str.lower()
- 某列转成大写:
DataFrame缺失值填充:
- 全局填充:
df.fillna(value=用来填充的值)
- 某列填充缺失值:
df[列名].fillna(value=用来填充的值)
- 全局填充:
DataFrame合并相同行:`
left = pd.DataFrame({'key': ['foo1', 'foo2'], 'one': [1, 2]}) right = pd.DataFrame({'key': ['foo2', 'foo3'], 'two': [4, 5]})print(left) print(right)# 按照 key 列对齐连接,只存在 foo2 相同,所以最后变成一行 pd.merge(left, right, on='key')
DataFrame的时间序列索引
dti = pd.date_range(start='2018-01-01', end='2018-12-31', freq='D') #freq是时间偏移量,默认是D,日
三、Matplotlib
1、基础概念:
Matplotlib包含的两个子模块用途:
matplotlib.pyplot 是基础的画图工具
matplotlib.pylab 是设置字体的工具
常用语法
from matplotlib import pylab from pylab import mpl mpl.rcParams['font.sans-serif'] = ['字体']
2、基本设置
画板整体设置
画板设置语句 含义 举例 举例含义 plt.grid 是否让图像出现网格 plt.grid(True) 有网格 plt.axis 对xy轴包围的区域的设置 plt.axis(‘tight’) 所有数据可见(详细看下表) plt.xlim 设置横坐标轴的最小值和最大值 plt.xlim(-1,20) x轴范围是-1到20 plt.ylim 设置纵坐标轴的最小值和最大值 plt.ylim(-1,20) y轴范围是-1到20 plt.figure(figsize=(x,y)) 设置画板的大小 plt.figure(figsize=(7,4)) 设置画板是7*4大小 plt.title 设置画板的标题 plt.title(‘画板’) 设置画板标题为’画板’ plt.xlabel 设置画板的x坐标名字 plt.xlabel(‘x’) 设置x轴名字为x plt.ylabel 设置画板的y坐标 plt.ylabel(‘y’) 设置y轴名字为y plt.legend 设置图例的位置 plt.legend() 默认图例自适应放置(更多见下图) plt.xticks 改变x坐标的索引值 plt.xticks([1,2,3],[‘a’,‘b’,‘c’]) 则1对应’a’,2对应’b’,3对应’c’ plt.yticks 改变y坐标的索引值 plt.yticks([1,2,3],[‘a’,‘b’,‘c’]) 则1对应’a’,2对应’b’,3对应’c’ figure详解:
plt.figure(num,figsize) #num指的是取第几块画布 #figsize是设置画布大小
axis的参数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xn3zmlqf-1571807652566)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1567909886384.png)]
legend常见参数
使用方法:
plt.legend(loc=数字)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Qj8sTt8-1571807652567)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1567909993404.png)]
3、基本图形操作
折线图
plt.plot(x,y) #其中x是横坐标列表 #y是纵坐标列表 plt.plot(x,y,label='图例名字',lw=线条粗细(数字),color='颜色') #更加复杂的参数,包括图例,线条粗细,颜色。 #具体参数见下表
颜色
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UqqhvemO-1571807652569)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1567910451439.png)]
线条样式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xu6WbdTQ-1571807652571)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1567910505141.png)]
柱形图
plt.bar(x,y) #其中x是横坐标,y是纵坐标 plt.bar(x,y,label=,color=) #创建柱形图,且给绘入的一组柱形图加颜色以及对应的图例
直方图
plt.hist(data, bins=, normed=, facecolor='', edgecolor='', alpha=) """ 绘制直方图 data:必选参数,绘图数据 bins:直方图的长条形数目,可选项,默认为10 normed:是否将得到的直方图向量归一化,可选项,默认为0,代表不归一化,显示频数。normed=1,表示归一化,显示频率。 facecolor:长条形的颜色 edgecolor:长条形边框的颜色 alpha:透明度 """ #实例: plt.hist(data, bins=40, normed=0, facecolor="blue", edgecolor="black", alpha=0.7)
散点图
plt.scatter(x,y) #创建散点图,其中x是横坐标,y是纵坐标 plt.scatter(x,y,label=,color=,s=,marker='') #其中label是图例,color是颜色 #s是点的大小:比如25 #marker是点的形状比如:o
饼图
plt.pie( x, labels=[,,,], startangle=数字, shadow=True/False, explode=(,,,), autopct='格式' ) #即x是数据 #labels后的[,,,]是要给给一块对应加的图例列表 #startangle是从哪里开始切 #shadow是加阴影 #explode是分开角度 #autopct是每一块占比数据的格式#比如: x=[1,2,3,4,5] plt.pie( x, labels=['吃饭','玩','工作','学习','睡觉'], startangle=90, shadow=True, explode=(0,0,0,0.1,0), autopct='%2.3f' ) #其中%2.3f是整数保留2位小数保留3位
堆叠图
plt.stackplot(x,y,z,e,f) #其中x是横坐标,y,z,e,f的每一个元素对应着横坐标x的每一个值,进行堆叠。 #比如 x=[1,2,3] y=[10,20,30] z=[100,200,300] plt.stackplot(x,y,z) #表明x为横坐标,第1天对应y是10,z是100。第2天y是20,z是200。 #同样第3天y是30,z是300。 plt.stackplot(x,y,z,color=[,,]) #同时设置颜色#加图例方法: #首先先画空图 plt.plot([],[],color='',label=) plt.plot([],[],color='',label=) plt.stackplot(x,y,z,color=[,,]) #这样会对应颜色加图例
4、子图设置:
获得子图以及切换子图
plt.figure(num) #获得画布1 plt.subplot(nij) #切换子图#其中,plt.figure(num)指定是切换到那个画布,可以随机增加 #plt.subplot(ijn)中的i与j是几行几列,默认从1开始 #n是第几个子图,从上到下#例子: plt.figure(1) plt.subplot(211) plt.subplot(212) #获得画布1,切换子图1,切换子图2
5、文字说明
在任意位置添加文字
plt.text(x,y,'文字') #在坐标(x,y)加文字
在任意位置添加箭头文字:
plt.annotate('文字',xy=(x,y),xytext=(x,y),arrowprops={facecolor='black',shrink=0.05})#文字是要注释的文字,xy是箭头,xytext是箭尾,arrowprops是字典格式,里面有指针颜色,粗细
Python做编程题的GK总结
1、字母与数字之间的ascill值转换
- 字母转ascill值数字:ord(‘字母’)
- 数字转ascill值字母:chr(数字)
例如:
>>> chr(97)
'a'
>>> ord('a')
97
a-z:97-122
A-Z:65-90
a-z0-9_- ↩︎
a-z0-9_- ↩︎
\u2E80-\u9FFF ↩︎
\s\S ↩︎
0-9 ↩︎
习题 ↩︎
\s\S ↩︎
0-9 ↩︎
\s\S ↩︎
Python个人总结(基础+进阶)相关推荐
- Python网络爬虫基础进阶到实战教程
文章目录 认识网络爬虫 HTML页面组成 Requests模块get请求与实战 效果图 代码解析 Post请求与实战 代码解析 发送JSON格式的POST请求 使用代理服务器发送POST请求 发送带文 ...
- 计算机编程书籍-笨办法学Python 3:基础篇+进阶篇
编辑推荐: 适读人群 :本书适合所有已经开始使用Python的技术人员,包括初级开发人员和已经升级到Python 3.6版本以上的经验丰富的Python程序员. "笨办法学"系列, ...
- python开发需要掌握哪些知识-Python基础进阶需要掌握哪些知识点?
Python基础进阶需要掌握哪些知识点?Python将是每个程序员的标配,有编程基础再掌握Python语言对于日后的升职加薪更有利.Python语言简洁利于理解,语法上相对容易能够让开发者更专注于业务 ...
- python flask快速入门与进阶-Flask基础进阶与python flask实战bbs教程
├─Flask基础进阶 │ 01-HTTP 基础知识.mp4 │ 02-python CGI 与 WebServer.mp4 │ 03-virtuanenv配置及Flask快速示例.mp4 │ 04- ...
- Python基础进阶
Python第二周笔记 2019年3月25日 文章目录 Python第二周笔记 一.函数进阶 MAP Filter Reduce 二.模块 三. 文件方法 **内建函数** Time 模块 read/ ...
- Python爬虫零基础到进阶(课程说明)
Python爬虫零基础到进阶 课程介绍总结 学-练-问 跟着学.多做多练.不懂就问.坚持就是胜利! 作业 飞书布置,作业提交放到群里,老师批改. 代码量 python基础: 十一次课,学会python ...
- Python训练营—Tesk3—Python基础进阶—从函数到高级魔方方法
Python基础进阶--从函数到高级魔方方法 目录 Python基础进阶--从函数到高级魔方方法 一.函数 1.函数的定义 2.函数的调用 3.函数参数 4.变量作用域 ...
- python可以从大到小循环嘛_无需编程基础,Python从入门到进阶大法
原标题:无需编程基础,Python从入门到进阶大法
- 视频教程-快速入门Python基础教程_Python基础进阶视频-Python
快速入门Python基础教程_Python基础进阶视频 十余年计算机技术领域从业经验,在中国电信.盛大游戏等多家五百强企业任职技术开发指导顾问,国内IT技术发展奠基人之一. 杨千锋 ¥199.00 立 ...
- 大神匠心打造-零基础到Python工程师视频教程全套白嫖【基础+进阶+项目实战】
从小白到python开发工程师,只需这套系统教程就够了!!! [零基础python开发工程师视频教程全套,基础+进阶+项目实战] 详情 day1 至day28,python基础: 等级1(python ...
最新文章
- gprs发送信号对方如何接收_和接收缓冲区比较:Netty发送缓冲区是如何设计的,why?...
- 运行一个程序时如何打印出执行程序的时间
- 【杂谈】三人行必有AI,你会在其一吗?
- 迪杰斯特拉--- 模板(求最短路径/输出路径/所有路径都可以走的做法)
- 写一个使两个整数进行交换的方法(不能使用临时变量) 【前端每日一题-27】...
- 盘点Spring Boot最核心的27个注解
- npm run report,打包,包资源 ,vue大小,vue资源大小
- win10 安装db2 10.1 并使用DBserver连接db2数据库
- redis 备份与恢复
- 怎么用wps做区域分布图_wps演示制作漂亮的组织结构图
- Android中Intent的介绍
- PETA 数据集下载
- 如何把很多照片拼成一张照片_怎样用手机将多张照片拼成一张组合图
- 系统时间自动校对 让你准时每一天
- nginx转发https:SSL_do_handshake() failed
- windows10下载链接
- dup/dup2的用法及详解(转)
- 专题一 · 1004
- Job中织梦标签的调用
- 梯度下降及一元线性回归[python代码](二)
热门文章
- android LBS模式,android: 如何开启webview的LBS功能
- 74hc595级联c语言程序,stm32使用三片74HC595级联程序代码
- Pytorch安装教程
- 太美医疗:药物警戒(PV)人员的职业发展之道
- 京东方10.1寸1280*800薄屏EV101WXM-N10-BOE工业屏
- WZ-S甲醛传感器使用说明代码应用案例笔记
- POI Invalid column index (-5).Allowable column range for EXCEL2007 is (0..16383) or (‘A‘..‘XFD‘)问题解决
- 计算机桌面性能4.4怎么办,台式CPU性能怎么看?桌面CPU天梯图2018年1月更新版 (全文)...
- 企业信息化将推动企业组织结构和管理模式的变革
- php 获取当前 周,php如何获取当前时间是第几周