str 字符串函数
*capitalize
字符串首字母大写
*title
每个单词首字母大写
*upper
所有字母大写
*lower
所有字母小写
*swapcase
大小写互换
*len
计算字符串长度
*count
统计字符串某个字符的出现的次数
*find
查找某个字符串第一次出现的索引位置,找不到返回-1
字符串.find("字符",开始索引,结束索引)
*startswith
判断是否以某个字符或者字符串开头
字符串.startswith("字符",开始索引,结束索引) 如果存在返回True,否则返回False
*endswith
判断是否以某个字符或者字符串结尾
字符串.startswith("字符",开始索引,结束索引) 如果存在返回True,否则返回False
*isupper
判断字符串是否全是大写
*islower
判断字符串是否全是小写
*isdecimal
检测字符串是否是纯数字
*ljust
填充字符原字符居左
*rjust
填充字符原字符居右
*center
填充字符原字符居中
*strip
去除两边空白字符或指定字符
*lstrip
去掉左边指定字符
*rstrip
去掉右边指定字符
*split
按某字符将字符串分割成列表(默认是空格)从左到右
*rsplit
按某字符将字符串分割成列表(默认是空格)从右到左
*join
按某字符将列表拼接起来变成字符串
*replace
将旧字符替换成新字符
*isinstance() 
*函数来判断一个对象是否是一个已知的类型,类似 type()。
isalpha
判断一个对象是否是字母和中文字符

list列表函数
*append
向列表的末尾添加新的元素
*insert
在指定索引前插入元素 索引在前,值在后
*extend
迭代追加所有元素
*pop
通过索引删除指定元素,默认最后一位
*remove
指定值删除,多个值删除第一个
*del
删除指定范围
*clear
清空列表
*index
获取某个值的索引,可指定范围,如 lst.index("abc",3,5)
*count
获取某个值的出现的次数    #字符串可以确定范围 ,列表不行
*sort
从小到大排序  从大到小排序lst.sort(reverse=True)
*reverse
反转列表顺序

dict字典函数
*fromkeys
创建一组键和指定值的字典
*pop
通过键去删除键值(若没有该键可设置默认值,预防报错)如res = dic.pop("a","没有这个键!")
*popitem
删除最后一位键和键值
*clear
清空字典
del
删除一位键和键值
*update
批量更新(没有就添加)
*get
获取键位值,有该键可设置默认值,预防报错
*keys
将字典的键组合成可迭代的对象
*values
将字典的键值组合成可迭代的对象
*items
将字典的键值组合成一个个元组,形成新的可迭代对象

set集合操作
  &      求交集
   -      求差集
   |       求并集
   ^      求对称差集
 < ,>    判断是为子,父集
*isdisjoint()
检查两个集合是否不相交 不相交True,相交False
set集合函数
*add
向集合添加数据一次一个
*updat
迭代的添加 一次一堆
*clear
清空集合
*remove()
删除指定值,没有则报错  了解
*pop
随机删除一个值
*discard()
删除指定值,不存在不删除 推荐使用
*frozenset
冰冻集合,让集合只能交差并补

文件操作
fp = open("ceshi1.txt",mode="w",encoding="utf-8")
打开文件

fp.write()
写入内容

fp.read()
读取内容

fp.close()
关闭内容

encode
将字符串转换成字节流(Bytes流)  编码

decode
将字节流(Bytes流)转换成字符串  解码

seek(0)     
调整光标位置在开头

seek(0,2)  
调整光标位置在末尾

f.seek():指针移动    以字节为单位
三种模式:

0(默认):参照文件开头

1                :参照指针当前位置

2                :参照文件末尾

r    可读     
b    二进制模式
w    可写(覆盖试)
a    可写(末尾追加)
+    字母带此符号可读可写

read  
读取文件中所有字符

seek 
移动光标位置 中文可能会报错

tell
计算左侧所有的字节数

with open("集合.png",mode="rb") as fp:
打开文件,可省写close()

fp.flush()
手动把缓冲区里面的内容写入文件当中

readable()
判断文件对象是否可读

writable()
判断文件对象是否可写

readline()
读取一行内容

readlines()
将文件中的内容按照换行读取到列表当中

writelines()
将内容是字符串的  可迭代性数据写入文件中

truncate
把要截取的字符串提取出来,然后清空内容将提取的字符串重新写入文件中 (字节)

函数操作

def func():
       pass
定义函数

func()
调用函数

(函数的定义处)
形参: 普通形参(位置) , 默认形参 , 普通收集形参 , 命名关键字形参 , 关键字收集形参

def s_star(a,b = 0,c,*rags,d = 0,**kwargs)

(函数的调用处)
实参: 普通实参,关键字实参

* 和 ** 在函数的定义处,用来做收集操作,打包
* 和 ** 在函数的调用处,用来做打散操作,解包

参数定义的顺序:
普通参数 -> 默认参数 -> 普通收集参数 -> 命名关键字参数 -> 关键字收集参数

return 
返回值 (六大标准数据类型 , 还有类和对象,函数)

局部变量 : 在函数内部定义的变量(局部命名空间)
全局变量 : 在函数外部定义的或者使用global在函数内部定义(全局命名空间)

global
在函数内部定义或者修改一个全局变量

函数之间可以互相嵌套
外层的叫做外函数
内层的叫做内函数

LEGB原则
找寻变量的调用顺序依据就近原则,从下往上 从里向外 依次寻找

nonlocal 
修改局部变量且只能修改局部变量

locals 
获取当前作用域中所有变量

globals() # Python 内置函数
 函数会以字典类型返回当前位置的全部全局变量。

globals 如果在全局,调用globals之后,获取的是打印之前的所有变量,返回字典,全局空间作用域
globals 如果在局部,调用globals之后,获取的是调用之前的所有变量,返回字典,全局空间作用域

闭包函数:
如果内函数使用了外函数的局部变量,
并且外函数把内函数返回出来的过程,叫做闭包
里面的内函数是闭包函数
def qwq():
    look = ":)"
    def qaq():
        print("微笑表情{}".format(look))
    return qaq
a = qwq()
a()

__closure__
获取闭包函数使用的变量
例:res = func.__closure__

cell_contents 
用来获取单元格对象当中的闭包函数
jiejie = res[0].cell_contents

# 通过获取单元格对象 -> 获取单元格对象中的内容 -> 实际的调用

__closure__         cell_contents  :
print(meimei.__closure__[0].cell_contents)

闭包的意义:
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.

lambda 
匿名函数
例:func = lambda x,y : x if x>y else y  (传递两个数, 返回较大的那一个)

迭代器
能被next调用,并不断返回下一个值的对象,叫做迭代器(对象)

iter
定义一个迭代器
setvar = {"a","b","c","d"}
it = iter(setvar)
print(it)

"__iter__" ,"__next__"
判断一个迭代器
res = "__iter__" in dir(it) and "__next__" in dir(it)
print(res)

Iterator,Iterable
迭代器(要导入库:from collections import Iterator,Iterable)
# res = isinstance(it,Iterator) 判断迭代器
# res = isinstance(it,Iterable) 判断迭代对象

高阶函数:
map 
map(func,Iterable)
把Iterable中的数据一个一个拿出来,扔到func函数中做处理
把处理之后的结果放到迭代器当中,最后返回迭代器

filter
filter(func,iterable))
功能: 过滤数据
    return True  当前这个数据保留
    return False 当前这个数据舍弃

reduce
reduce(func,iterable)
功能:计算数据
    先把iterable中的前两个值拿出来,扔到func当中做运算,
    把计算的结果和iterable中的第三个元素在扔到func当中做运算,
    再把结果算出来,和第四个元素做运算,以此类推
    直到所有结果运算完毕.返回该结果

sorted   
sorted(iterable,key=函数,reverse=False)
功能:排序
iterable:可迭代型数据(容器类型数据,range对象,迭代器)
key     :指定自定义函数或内置函数
reverse :代表升序或者降序 , 默认是升序(从小到大排序) reverse=False

推导式
通过一行循环判断,遍历一系列数据的方式
三种方式:
    [val for val in Iterable]
    {val for val in Iterable}
    {k:v for k,v in Iterable}

enumerate
将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
例:
lst = ["东邪","西毒","南帝","北丐"]
it = enumerate(lst,1)
print(list(it))
#run   [(1, '东邪'), (2, '西毒'), (3, '南帝'), (4, '北丐')]

from collections.abc import Iterator,Iterable

collections.abc 
Iterator迭代器
Iterable可迭代性数据

zip()
将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中

生成器
生成器本质是迭代器,允许自定义逻辑的迭代器
 (1)生成器表达式  (里面是推导式,外面用圆括号)   例:gen = (i*2 for i in range(1,11))
 (2)生成器函数    (用def定义,里面含有yield)
例:def gan1():
    print("~~~~~~1")
    yield 1
gen = gan1()
a = next(gen)

### send
# next和send区别:
    next 只能取值
    send 不但能取值,还能发送值
# send注意点:
    第一个 send 不能给 yield 传值 默认只能写None
    最后一个yield 接受不到send的发送值
    send 是给上一个yield发送值    
yield 类似于 return
共同点在于:
执行到这句话都会把值返回出去
不同点在于:
yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的
位置往下走而return直接终止函数,每次重头调用.

yield from 
将一个可迭代对象变成一个迭代器返回

(1).递归是一去一回的过程,
    调用函数时,会开辟栈帧空间,函数执行结束之后,会释放栈帧空间
    递归实际上就是不停的开辟和释放栈帧空间的过程
    每次开辟栈帧空间,都是独立的一份,其中的资源不共享

(2).触发回的过程
    1.当最后一层栈帧空间全部执行结束的时候,会触底反弹,回到上一层空间的调用处
    2.遇到return,会触底反弹,回到上一层空间的调用处,
    
(3).写递归时,必须给与递归跳出的条件,否则会发生内存溢出,蓝屏死机的情况.
    如果递归层数过多,不推荐使用递归

# 递归写法
def jiecheng(n):
    if n <= 1:
        return 1
    return n*jiecheng(n-1)
res = jiecheng(5)
print(res)

尾递归
"""为了避免用户乱传参数,把endval这个参数隐藏起来"""
def outer(n):
    def jiecheng(n,endval=1):
        if n <= 1:
            return endval
        return jiecheng(n-1,endval*n)
        
    return jiecheng(n) # jiecheng(n-1,endval*n)
res = outer(5)
print(res)

内置方法
abs()
绝对值函数

round()
四舍五入 “一位小数奇进偶不进”

sum()
计算一个序列和

max()
获取一个序列里边的最大值

min()
获取一个序列里边的最小值

pow()    
计算某个数值的x次方 pow(参数1,参数2[,参数3]) 参数3代表的是取余数

range
产生指定范围数据的可迭代对象

bin
将10进制数据转化为二进制

oct    
将10进制数据转化为八进制

hex    
将10进制数据转化为16进制

chr    
将ASCII编码转换为字符

ord    
将字符转换为ASCII编码

exec    把字符串转化成一个python代码执行,
eval    从一个表达式里返回值。
exec没有返回值,eval有返回值

repr
不转义字符输出字符串

input  
接受输入字符串

hash   
生成哈希值
相同的两个数据经过哈希算法运算得出的结果一定相同

数学模块
import math
ceil()
向上取整操作 (对比内置round)

floor() 
向下取整操作 (对比内置round)

pow()  
计算一个数值的N次方(结果为浮点数) (对比内置pow)

sqrt() 
开平方运算(结果浮点数)

fabs() 
计算一个数值的绝对值 (结果浮点数)

modf() 
将一个数值拆分为整数和小数两部分组成元组

copysign()  
将参数第二个数值的正负号拷贝给第一个 (返回一个小数)

fsum()
将一个容器数据中的数据进行求和运算 (结果浮点数)

pi
圆周率常数

random 随机模块
import random
random() 
获取随机0-1之间的小数(左闭右开) 0<= x <1

randrange() 
随机获取指定范围内的整数(包含开始值,不包含结束值,间隔值) **

randint() 
随机产生指定范围内的随机整数 (了解)

uniform() 
获取指定范围内的随机小数(左闭右开)

choice()  
随机获取序列中的值(多选一)

sample()  
随机获取序列中的值(多选多) [返回列表]

shuffle() 
随机打乱序列中的值(直接打乱原序列)

ascll码表
chr
# 小写字母:97~122
#大写字母: 65~90

序列化模块 pickle
import pickle
dumps 
把任意对象序列化成一个bytes

loads
把任意bytes反序列化成原来数据

dump  
把对象序列化后写入到file-like Object(即文件对象)

load  
把file-like Object(即文件对象)中的内容拿出来,反序列化成原来数据

json 用法
#所有编程语言都能够识别的数据格式叫做json,是字符串
dumps 
把任意对象序列化成一个str

loads 
把任意str反序列化成原来数据

dump  
把对象序列化后写入到file-like Object(即文件对象)

load 
把file-like Object(即文件对象)中的内容拿出来,反序列化成原来数据

# json 和 pickle 两个模块的区别:
(1)json序列化之后的数据类型是str,所有编程语言都识别,
   但是仅限于(int float bool)(str list tuple dict None)
   json不能连续load,只能一次性拿出所有数据
(2)pickle序列化之后的数据类型是bytes,
   所有数据类型都可转化,但仅限于python之间的存储传输.
   pickle可以连续load,多套数据放到同一个文件中

time 时间模块
time()      
获取本地时间戳

localtime()    
获取本地时间元组

mktime()
通过时间元组获取时间戳

ctime() 
获取本地时间字符串(参数是时间戳,默认当前)

asctime()
通过时间元组获取时间字符串(参数是时间元组)

sleep()         
程序睡眠等待

strftime()
格式化时间字符串(格式化字符串,时间元祖)
strptime()
将时间字符串通过指定格式提取到时间元组中(时间字符串,格式化字符串)

strftime => 把时间元组 -> 时间字符串
strptime => 把时间字符串 -> 时间元组

perf_counter()
用于计算程序运行的时间

zipfile 压缩模块
#zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])
ZipFile()
#(路径包名,模式,压缩or打包,可选allowZip64)
例:zipfile.ZipFile("1424.zip","w",zipfile.ZIP_DEFLATED)
******
mode                # r w a
compression :
     #zipfile.ZIP_STORED        只是存储模式,不会对文件进行压缩,这个是默认值
     #zipfile.ZIP_DEFLATED     对文件进行压缩
allowZip64          #zip文件大小超过2G,应该将allowZip64设置为True。
******

#压缩文件
#1.ZipFile()                写模式w打开或者新建压缩文件
#2.write(路径,别名)     向压缩文件中添加文件内容
#3.close()

#解压文件
#1.ZipFile()                 读模式r打开压缩文件
#2.extractall(路径)       解压所有文件到某个路径下
#  extract(文件,路径)    解压指定的某个文件到某个路径下
#3.close()                    关闭压缩文件

#追加文件(支持with写法)
ZipFile()                      追加模式a打开压缩文件

#查看压缩包中的内容
namelist()

tarfile 压缩模块
.tar  |  .tar.gz  |   .tar.bz2

w     单纯的套一个后缀 打包
w:bz2 采用bz2算法 压缩    
w:gz  采用gz算法 压缩

#压缩文件
#1.open('路径包名','模式','字符编码') 创建或者打开文件 
#2.add(路径文件,arcname="别名") 向压缩文件中添加文件
#3,close() 关闭文件

#解压文件
#1.open('路径包名','模式','字符编码') 读模式打开文件 
#2.extractall(路径)      解压所有文件到某个路径下
#  extract(文件,路径)    解压指定的某个文件到某个路径下
#3.close()

#追加文件                  
#1.open('路径包名','模式','字符编码')追加模式 a: 打开压缩文件 正常添加即可 
#2.add(路径文件,arcname="别名") 向压缩文件中追加文件
#3.close()

#查看压缩包中的内容
getnames()

os 对系统进行操作
system()         
在Python中执行命令

popen()          
反回执行命令对象,用read方法读出字符串

listdir()        
获取指定文件夹中所以内容的名称列表

getcwd()         
获取当前文件所在的默认路径

print(__file__)  
获取当前的路径+文件

chdir()         
修改当前文件工作的默认路径

environ()      
获取或修改环境变量

name         
获取系统标识

sep         
获取路径分割符号

linesep
获取系统的换行符号

mknod()
创建文件

mkdir()
创建目录(文件夹)

remove()
删除文件

rmdir()
删除目录(文件夹) #只能删除空目录

rename()
对文件重命名

makedirs()
递归创建文件夹

removedirs()
递归删除文件夹

shutil 模块
import shutil
copyfileobj() 
复制文件的内容  #打开文件后在复制

copyfile() 
复制文件内容

copymode()
复制文件权限

copystat()
复制所有状态信息,不包括内容

copy()
复制文件权限和内容

copy2()
复制所有状态信息

copytree()
拷贝文件夹里所有内容

rmtree()
删除文件夹内及其所有内容

move()
移动文件或文件夹

os.path 路径模块
import os
os.path.basename()
反回文件名部分

os.path.dirname()
反回文件路径部分

os.path.splist()
将路径拆分成单独的文件部分和路径部分 组合成一个元组

os.path.join()
将多个路径和文件组成新的路径

os.path.splitext()  
将路径分割为后缀和其他部分

os.path.getsize()
获取文件的大小

os.path.isdir()
判断当前路径是否为一个文件夹

os.path.isfile()
判断当前路径是否为一个文件

os.path.islink()
判断当前路径是否为一个链接

import time
os.path.getctime()
windows文件创建时间, liunx权限的改动时间(反回时间戳)

os.path.getmtime()
获取文件最后一次修改时间(反回时间戳)

os.path.getatime()
获取文件最后一次访问时间(反回时间戳)

os.path.exists()
检测指定的路径是否存在

os.path.isabs()
检测一个路径是否是绝对路径

os.path.abspath()
将相对路径转化为绝对路径

tarfile 压缩模块
.tar  |  .tar.gz  |   .tar.bz2

w     单纯的套一个后缀 打包
w:bz2 采用bz2算法 压缩    
w:gz  采用gz算法 压缩

#压缩文件
#1.open('路径包名','模式','字符编码') 创建或者打开文件 
#2.add(路径文件,arcname="别名") 向压缩文件中添加文件
#3,close() 关闭文件

#解压文件
#1.open('路径包名','模式','字符编码') 读模式打开文件 
#2.extractall(路径)      解压所有文件到某个路径下
#  extract(文件,路径)    解压指定的某个文件到某个路径下
#3.close()

#追加文件                  
#1.open('路径包名','模式','字符编码')追加模式 a: 打开压缩文件 正常添加即可 
#2.add(路径文件,arcname="别名") 向压缩文件中追加文件
#3.close()

#查看压缩包中的内容
getnames()

正则表达式
import re
re.findall
符合正则表达式的字符串存在 列表中返回

re.search
匹配成功 返回一个匹配的对象,否则返回None。

group
返回的是匹配到的结果
groups  
返回的是括号分组里面的内容

预定义字符集
\d
匹配数字
\D
匹配非数字

\w
匹配字母或下划线
\W
匹配非字母或下划线

\s
匹配任意空白字符(\n  \t  \r)
\S
匹配任意非空白字符(\n  \t  \r)

\n
匹配一个换行符号

\t
匹配一个制表符号

\b 
本身也是转义字符 : 退格(把光标向左移动一位)

.
匹配一个任意字符 除了\n

字符组[]
字符组列举出来的字符当中抽取,默认一个,如果没有返回空

-
代表到,表示范围
例子:0-9  a-z  A-Z

^
在字符组中,开头的位置 表示除了字符组里面的字符都匹配


表示转义
\^ 表示 ^ 字符

量词

匹配0个或者1个a    a表示?前面的表达式或者字符

+
匹配1个或者多个a

*
匹配0个或者多个a

{m,n}
匹配m个至n个a

#贪婪匹配:   
默认向更多次数匹配  (底层用的是回溯算法)

非贪婪匹配:  
默认向更少次数匹配 (量词的后面加?号)
量词( * ? + {} )加上问号?表示非贪婪 惰性匹配
例:.*?w  表示匹配任意长度任意字符遇到一个w就立即停止

边界符 \b
\b 本身也是转义字符 : 退格(把光标向左移动一位)
word
右边界: d\b
左边界: \bw


匹配字符串的开始(必须以... 开头)

匹配字符串的结尾(必须以... 结尾)
当使用^ 和 $ 符号的时候,要把字符串看成整体

分组练习(用圆括号)
() 优先显示括号里面的内容

?: 取消显示括号里面的内容

|  代表或 , a|b 匹配字符a 或者 匹配字符b (把字符串长的写在前面,字符串短的写在后面)

search 的用法
通过正则匹配出第一个对象返回
group
取出search反回对象中的值
返回的是括号分组里面的内容

\1 
代表反向引用第一个括号内容  
\2代表反向引用第二个括号内容

(?P<组名>正则表达式) 给这个组起一个名字
(?P=组名) 引用之前组的名字,把该组名匹配到的内容放到当前位置

findall  匹配字符串中相应内容,返回列表 [用法: findall("正则表达式","要匹配的字符串")]
search   通过正则匹配出第一个对象返回,通过group取出对象中的值
match    验证用户输入内容
split    切割
sub      替换 
subn     替换 
finditer 匹配字符串中相应内容,返回迭代器
compile  指定一个统一的匹配规则

常用修饰符    说明
re.I        使匹配对大小写不敏感
re.M        使每一行都能够单独匹配(多行匹配),影响 ^ 和 $
re.S        使 . 匹配包括换行在内的所有字符

模块导入
from .. import .. 
从哪里导入什么什么东西

import.引入并起别名 , as 后面写这个模块的别名

# import导模块的时候,会从sys.path提供的路径下去找,找不到就报错
# import sys
# print(sys.path)

__name__
#返回模块名字的魔术属性 __name__
如果当前文件是直接运行的,返回__main__
如果当前文件是间接导入的,返回当前文件名(模块名)

.    当前路径
..   上一级路径
...  上一级的上一级
.... 上一级的上一级的上一级
.....   (这里的点是无限的)

面向对象
类的基本结构
1.成员属性
2.成员方法

类的命名
# 驼峰命名法 : 推荐起类名的时候,使用大驼峰命名法.

import types
types.MethodType(方法,对象j)

查看类对象内部成员使用__dict__,返回的是字典

# 类和对象之间的区别
对象可以调用类中的成员属性和方法,返过来,类不能调用对象中的成员.
类中的成员属性和方法归属于类本身,对象可以使用,但是没有修改和删除的权利.
对象在调用相应成员时,先看看自己有没有
    如果有,调用自己的
    如果没有,调用类中的成员
    如果类中成员也没有,直接报错.

删除类中的成员方法
del 类.成员方法

删除对象中的成员方法
del 对象.成员方法

关于python私有化的实现方法: 改名策略
_类名 + 私有成员 => 改名策略

类的继承
单继承
如果一个类继承另外一个类,
该类叫做子类(衍生类),被继承的类叫做父类(基类,超类)
python中,所有的类都默认继承父类object

子类优先调用自己的,如果没有,调用父类中的
如果都没有,直接报错

(1)super本身是一个类 super()是一个对象 用于调用父类的绑定方法
(2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
(3)super用途: 解决复杂的多继承调用顺序

super()只调用父类的相关公有成员,不会调用自己的本类成员,父类没有直接报错.
super()在调用父类方法时,只调用父类的绑定方法,默认传递参数是本类的对象self

self 和 super()的区别
self    在调用成员时,自己的类对象中存在该成员,调用自己的,没有,调用父类的.如果都没有报错
super() 在调用成员时,父类的相关成员(属性,绑定方法),永远不会调用自己的.如果父类没有,直接报错.

mro 
列表 : super用途的一个体现.解决复杂的多继承调用顺序关系

issubclass 
判断子父关系 (应用在类当中,判断子父关系)

isinstance 
(应用在对象和类之间,判断类型)

__init__
__init__魔术方法(构造方法)
触发时机:实例化对象,初始化的时候触发
功能:为对象添加成员
参数:参数不固定,至少一个self参数
返回值:无

__new__(cls [,...])    instance = MyClass(arg1, arg2)    __new__ 在创建实例的时候被调用
__init__(self [,...])    instance = MyClass(arg1, arg2)    __init__ 在创建实例的时候被调用
__cmp__(self, other)    self == other, self > other, 等。    在比较的时候调用
__pos__(self)    +self    一元加运算符
__neg__(self)    -self    一元减运算符
__invert__(self)    ~self    取反运算符
__index__(self)    x[self]    对象被作为索引使用的时候
__nonzero__(self)    bool(self)    对象的布尔值
__getattr__(self, name)    self.name # name 不存在    访问一个不存在的属性时
__setattr__(self, name, val)    self.name = val    对一个属性赋值时
__delattr__(self, name)    del self.name    删除一个属性时
__getattribute(self, name)    self.name    访问任何属性时
__getitem__(self, key)    self[key]    使用索引访问元素时
__setitem__(self, key, val)    self[key] = val    对某个索引值赋值时
__delitem__(self, key)    del self[key]    删除某个索引值时
__iter__(self)    for x in self    迭代时
__contains__(self, value)    value in self, value not in self    使用 in 操作测试关系时
__concat__(self, value)    self + other    连接两个对象时
__call__(self [,...])    self(args)    “调用”对象时
__enter__(self)    with self as x:    with 语句环境管理
__exit__(self, exc, val, trace)    with self as x:    with 语句环境管理
__getstate__(self)    pickle.dump(pkl_file, self)    序列化
__setstate__(self)    data = pickle.load(pkl_file)    序列化

基本的魔法方法    
__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)    (与上方相同,当左操作数不支持相应的操作时被调用)
__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)    定义赋值按位或操作的行为:|=
一元操作符
__neg__(self)    定义正号的行为:+x
__pos__(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)时的行为

对象
对象: 独立的存在或目标的事情
独立性:对象都存在清晰的边界,重点在于划分边界
功能性:对象都能表现出一些功能,操作行为
交互性:对象之间存在交互,如:运算和继承

python语言中所有数据都是对象、函数是对象,模块是对象
python所有类都继承于最基础类object
python语言数据类型的操作功能都是类方法的体现

OOP: 面向对象编程,一种编程思想,重点在于高抽象的复用代码
OOP把对象当作程序的基本单元,对象包含数据和操作数据的函数
OOP本质是把问题解决抽象以对象为中心的计算机程序

类:逻辑抽象和产生对象的模板,一组变量和函数的特定安排
对象:具体表达数据及操作的实体,相对于程序中的“变量”
实例化:从类到对象的过程,所有"对象"都源于某个“类”

面向对象术语概述
三个特性:封装、继承、多态
继承:基类、派生类、子类、父类、超类、重载
命名空间:程序元素作用域的表达
构造和析构:生成对象的和删除对象的过程

类的基本构建方法
class <类名>:
          [类描述 “documentation string”]
    <语句块>

类对象:Class Object
类定义后完成后,默认生成一个类对象
每一个类唯一只对象一个类对象,用于储存这个类的基本信息
类对象是type类的实例,表达type类型

<实例对象> = <类名>.([<参数>])
类的属性:类中定义的变量,用来描述类的一些特定参数
类的方法:类中定义且于类相关的函数,用来给出类的操作功能
属性和方法是类对外交互所提供的两种接口方式

类对象 vs 实例对象

类对象:维护每个Python类基本信息的数据结构
实例对象:python类实例后产生的对象,简称:对象
这是一组概念,类对象全局只有一个,实例对象可以生成多个

init() 构造函数
class<类名>:
    def __init__(self,<参数>)    #给出了参数就会生成一个具体的对象
        <语句库>              
类实例化时所使用的函数,可以接收参数并完成初识操作
__init__的使用说明
参数:第一参数约定时self,表示类实例本身,其他参数是实例参数
函数名:python内置函数
反回值:没有返回值 或返回None

self代表类的实例
slef是python面向对象中约定的一个参数
self 表示类的实例,在类内部,self用于组合访问实例相关的属性,和方法
相比,类名字代表类对象本身

实例方法: 实例对象对方法,由各实例对象独享,最常用的形式
类方法:类对象的方法,有所有实例对象共享
自由方法:类中的一个普通函数,由类所在命名空间管理,类对象独享
静态方法:类中的一个普通函数,由类对象和实例对象共享
保留方法:由双下划线开始和结束的方法,保留使用,__len__()

实例方法:
class <类名>:
    def<方法名>(self,<参数列表>):
        pass

类方法:
class<类名>:
    @classmethod     #装饰器  类方法定义必须
    def <方法名>(cls,<参数列表>):
        pass
# 类方法只能操作类属性和其他类方法,不能操作实例属性和实例方法  可以被对象和类调用

自由方法:  (就是一个普通的函数)
class <类名>:
    def <方法名>(<参数列表>):  #可以不需要self或cls这参数,可以没有参数
        pass
#只能操作类属性 类方法 ,不能操作实例属性和实例方法
#自由方法采用 <类名>.<方法名>(<参数列表>)方法使用,<类名>表示命名空间

静态方法: (定义在类的普通函数,且能够被所有实例对象共享)
class<类名>:
    @staticmethod     #装饰器  静态方法定义必须
    def <方法名>(<参数列表>): #可以理解为定义在类中的普通函数,可以没有参数
        pass
#只能操作类属性 类方法 ,不能操作实例属性和实例方法
# 静态方法采用 <类名>.<方法名>(<参数列表>) 或  <对象名>.<方法名>(<参数列表>) 方法调用

保留方法:
class <类名>:
    def<保留方法名>(<参数列表>): 一般都有self参数
        pass
#保留方法一般都对应类的某种操作,但操作产生时使用

sys.getrefcount()函数返回值为 被引用值+1

(函数的调用处)
实参: 普通实参,关键字实参

* 和 ** 在函数的定义处,用来做收集操作,打包 *接受的是元组  **接收的是字典
* 和 ** 在函数的调用处,用来做打散操作,解包

装饰器(decorator)
定义:装饰器用于拓展原来函数功能的一种语法,返回新函数替换旧函数
优点:在不更改原函数代码的前提下 给函数拓展新的功能

property
用property类装饰器,修饰的方法,变为描述符
效果:把类中方法变为属性使用,用来控制描述符的获取,设置,删除

反射
# 概念:通过字符串去操作类对象 或者 模块中的属性方法
# (1)类中的反射
#hasattr() 检测对象/类是否有指定的成员
#getattr() 获取对象/类成员的值
#setattr() 设置对象/类成员的值
#delattr() 删除对象/类成员的值

# (2)模块的反射
sys.modules 返回一个系统字典,字典的键是加载的所有模块

异常处理:
程序错误分为两种:语法错误 和 异常错误
语法错误:代码没有按照python规定语法去写,发明创造产生的错误
异常错误:在代码语法正确的前提下,程序报错就是异常

try ... except ...
把有问题的代码放到try这个代码块当中
如果出现了异常,会直接执行except这个代码块中的内容
作用:防止异常抛错,终止程序.
except + 异常错误类 特指发生在这类异常错误时,要执行的分支

try ... finally ...  
不论代码正确与否,都必须执行的代码放到finally当中.

try .. except .. else ...
如果try这个代码块没有异常错误,执行else这个分支,反之就不执行

try .. except .. else .. finally .. 
如果try这个代码块没有异常错误,执行else这个分支,反之就不执行,
不论代码正确与否,都必须执行的代码放到finally当中.

for/while  ... else .. 
当循环遇到break异常终止循环时,不执行else分支,反之执行

主动抛出异常  raise
raise + 异常错误类  or 异常错误类对象

BaseException 所有异常类的父类(基类,超类)
Exception     常见异常类的父类

抑制报错:
try:
    raise BaseException
except BaseException:
    pass

自定义异常类 MyException (务必继承父类 BaseException)
例子:
class MyException(BaseException):
#(了解)系统底层获取行数和文件名的函数( 只有在程序异常时才能触发 ) 
def return_errorinfo(n):
    import sys
    f = sys.exc_info()[2].tb_frame.f_back
    if n==1:        
        return str(f.f_lineno)      #返回当前行数
    elif n == 2:    
        return f.f_code.co_filename #返回文件名

# 通过get_value 主动抛出异常
def get_value(n):
    try:
        raise
    except:
        return return_errorinfo(n)
class MyException(BaseException):
    def __init__(self,num,msg,line,file):
        # 错误号
        self.num = num
        # 错误信息
        self.msg = msg
        # 错误行号
        self.line = line
        # 错误文件
        self.file = file

sex = "雌雄同体"
try:
    if sex == "雌雄同体":
        # raise + 异常错误类 或者 异常错误类对象
        raise MyException(404,"醒醒吧老弟,人类没有雌雄同体~",get_value(1),get_value(2))
except MyException as e:
    # 对象.属性 
    print(e.num)
    print(e.msg)
    print(e.line)
    print(e.file)

IndexError                    索引超出序列的范围
KeyError                       字典中查找一个不存在的关键字
NameError                   尝试访问一个不存在的变量
IndentationError           缩进错误
AttributeError               尝试访问未知的对象属性
StopIteration                迭代器没有更多的值
AssertionError           断言语句(assert)失败
EOFError                      用户输入文件末尾标志EOF(Ctrl+d)
FloatingPointError         浮点计算错误
GeneratorExit                generator.close()方法被调用的时候
ImportError                   导入模块失败的时候
KeyboardInterrupt          用户输入中断键(Ctrl+c)
MemoryError                 内存溢出(可通过删除对象释放内存)
NotImplementedError     尚未实现的方法
OSError                         操作系统产生的异常(例如打开一个不存在的文件)
OverflowError               数值运算超出最大限制
ReferenceError             弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
RuntimeError                一般的运行时错误
SyntaxError                  Python的语法错误
TabError                     Tab和空格混合使用
SystemError                 Python编译器系统错误
SystemExit                   Python编译器进程被关闭
TypeError                    不同类型间的无效操作
UnboundLocalError       访问一个未初始化的本地变量(NameError的子类)
UnicodeError                 Unicode相关的错误(ValueError的子类)
UnicodeEncodeError      Unicode编码时的错误(UnicodeError的子类)
UnicodeDecodeError      Unicode解码时的错误(UnicodeError的子类)
UnicodeTranslateError    Unicode转换时的错误(UnicodeError的子类)
ValueError                     传入无效的参数
ZeroDivisionError           除数为零

反射
1.反射 (针对于类对象或者模块)
概念: 通过字符串去操作类对象或者模块当中的成员(属性或者方法)

hasattr() 
检测对象/类是否有指定的成员

对象
res = hasattr(对象名,"成员名") 
print(res) #有返回True  没有或私有成员返回False

res = hasattr(类名,"方法名")
print(res) #有返回True  没有或私有成员返回False

getattr() 
获取对象/类成员的值

对象
func = getattr(对象名,"方法名")  # 通过对象反射出来的方法是个绑定方法
func()


func = getattr(类名,"方法名")     # 通过类反射出来的方法是个普通方法
func(1)

# 反射的成员不存在时,可以设置一个默认值防止报错
res = getattr(对象名,"不存在的成员","默认值")
print(res)

setattr()
设置对象/类成员的值

# 对象
setattr(对象名,"成员名","成员值")
print(对象名.成员名)
# 类
setattr(类名,"成员名","成员值")
print(类名.成员名)
print(对象名.成员名)

delattr()
 删除对象/类成员的值

对象
delattr(对象名,"成员名")
print(对象名.成员名) error


delattr(类名,"成员名")
print(类名.成员名)   error

2.反射模块中的成员

import sys
print(sys.modules) # 返回的是系统模块的一个字典
# 获取当前本模块的对象 (通过__main__这个键来获取)
print(sys.modules["__main__"])

例子:
selfmodule = sys.modules["__main__"]
strvar = input("请输入你要反射的方法")
if hasattr(selfmodule,strvar):
    func = getattr(selfmodule,strvar)
    func()

网络编程:
网络开发的两大架构
c/s 架构 : client  server
B/S 架构 : Brower  server

(1)mac地址:标记一台机器的物理地址  (不可变)
(2)ip 地址:#标记一台机器的逻辑地址 (可变)

# ### 2.网络概念
# (1) ip windows ipconfig  linux ifconfig
ip地址的最后一位0或者255 两个数字不能用,
一般最后一位0表达的是网段,255代表广播地址

# (2) 网段
网段的作用:
    主要用来划分同一区域里的某些机器是否能够互相通信。
    在一个网段里可以不通过因特网,直接对话
判别的依据:
    如果IP地址和子网掩码相与得到的值相同就是同一网段     
#子网掩码:区分网段和主机
# 案例一
# ip 192.168.30.251
#子网掩码 255.255.255.0

# 端口: 某个程序与外界通讯的出口
# 范围: 0~65535 
# ip + 端口 访问这个世界上任何一台电脑里面的任何一个应用;
20 端口:FTP 文件传输协议(默认数据口)
21 端口:FTP 文件传输协议(控制)
22 端口:SSH 远程登录协议
25 端口:SMTP 服务器所开放的端口,用于发送邮件
80 端口:http,用于网页浏览,木马 Executor 开放此端口
443 端口:基于 TLS/SSL 的网页浏览端口,能提供加密和通过安全端口传输的另一种 HTTP
3306 端口:MySQL 开放此端口
自定义端口的时候起一个9000以后的端口号,不要乱用已知的端口号
应用层(应用层,表示层,会话层)
    封装数据:
        根据不同的协议,封装成对应格式的数据消息
        HTTP  [超文本传输协议]
        HTTPS [加密传输的超文本传输协议]
        FTP   [文件传输协议]
        SMTP  [电子邮件传输协议]

传输层:
    封装端口
        指定传输的协议(TCP协议/UDP协议)
    
网络层:
    封装ip
        版本ipv4 ipv6
    
数据链路层:
    封装mac地址
        指定链路层协议arp(ip->mac) / rarp (mac->ip)

物理层:
    打成数据包,变成二进制的字节流,通过网络进行传输
    
# arp协议 : 通过ip -> mac (arp地址解析协议)
"""通过交换机的一次广播和一次单薄找到对应mac物理地址"""

电脑a先发送arp的广播包,把mac标记成全FF-FF-FF-FF-FF-FF的广播地址
交换机接收到arp广播包,从下到上拆2层,到数据链路层得到mac
发现mac是全F的广播地址,重新打包,交换机开始广播,所有连接在这台
交换的的设备统一都会受到arp广播包,开始拆包
如果对应的是全F广播地址,直接跳过,继续向上找,如果ip不对,直接舍弃
路由器允许从下到上拆3层,拆到网络层,得到ip,找到其中的网段
重新把数据打包,发送给对应这个网段的那个接口(网关)
对应的接口设备是交换机,从下到上拆2层,全F广播地址,开始发送arp广播包
数据库服务器接收到arp广播包开始拆包,发现要找的机器就是自己.
于是把自己的ip->mac的对照数据,返回给对应的交换机.
交换机开始单播,让ip->mac的对照数据返回到开始处
原主机接收到了ip->mac的对照关系之后,更新一下自己的arp的解析表,方便下次使用
到此结束.

SYN 创建连接
ACK 确认响应
FIN 断开连接
# 三次握手
    客户端发送一个请求,与服务端建立连接
    服务端接受请求,发出响应,并且回应也要与客户端建立连接
    (服务端同意连接的请求 和 服务端与客户端建立连接的请求在一次响应当中完成了)
    客户端接受服务端的请求之后,把消息在回复响应给服务端.

# 数据传输
    客户端每次发送数据时,服务端每次都有响应,发一个回执消息来确认数据
    所以tcp协议,发送数据不丢包.保证数据稳定.

网络七层协议详解

https://baijiahao.baidu.com/s?id=1631493604924185432&wfr=spider&for=pc

socket 模块
tcp 
sk = socket.socket()         # 创建 socket 对象
host = "192.168.30.44"       #设置IP地址
port = 9000                # 设置端口
sk.bind((host,port) )          #绑定ip和端口号   被动接受TCP客户端连接
connect((host,port))      #客户机绑定ip和端口号主动   初始化TCP服务器连接
sk.listen()                #建立监听
conn,addr = sk.accept( )   #建立链接 conn返回新的socket, addr返回一个客户机IP地址和端口号的元组
"""recv 接受 send 发送"""
conn.recv(1024)         # 最多一次接受 1024 字节返回客户机发送的数据
# 6.四次挥手
conn.close()
# 7.退还端口
sk.close()

udp 
# 1.创建udp对象
sk = socket.socket(type=socket.SOCK_DGRAM)
“”“recvfrom接受 sendto发送"""
服务端
import socket
# 1.创建udp对象
sk = socket.socket(type=socket.SOCK_DGRAM)
# 2.绑定地址端口号
sk.bind( ("192.168.30.10",9000) )
# 3.udp服务器,在一开始只能够接受数据
while True:
    # 接受消息
    msg,cli_addr = sk.recvfrom(1024)
    print(msg.decode())
    print(cli_addr)
    message = input("服务端给客户端发送的消息是?:")
    # 发送数据
    sk.sendto(message.encode() , cli_addr)
# 4.关闭连接
sk.close()

客户机
import socket
# 1.创建udp对象
sk = socket.socket(type=socket.SOCK_DGRAM)
# 2.收发数据的逻辑
while True:
    # 发送数据
    message = input("客户端给服务端发送的消息是?:")
    sk.sendto(message.encode(), ("192.168.30.10",9000) )
    # 接受数据
    msg,addr = sk.recvfrom(1024)
    print(addr)
    print(msg.decode("utf-8"))
# 3.关闭连接
sk.close()

粘包
黏包出现的两种情况:
(1) 发送端发送数据太快
(2) 接收端接收数据太慢
# ### 服务端
import time
import socket
import struct
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sk.bind( ("127.0.0.1",9000) )
sk.listen()
conn,addr = sk.accept()
# 处理收发数据的逻辑
strvar = input("请输入你要发送的数据")
msg = strvar.encode()
length = len(msg)
res = struct.pack("i",length)  把任意长度数字转化成具有固定4个字节长度的字节流
# 第一次发送的是字节长度
conn.send(res)
# 第二次发送真实的数据
conn.send(msg)
# 第三次发送真实的数据
conn.send("世界真美好123".encode())
conn.close()
sk.close()

# ### 客户端
import socket
import time
import struct
sk = socket.socket()
sk.connect( ("127.0.0.1",9000) )
time.sleep(2)
# 处理收发数据的逻辑
# 第一次接受的是字节长度
n = sk.recv(4)
tup = struct.unpack("i",n)  把4个字节值恢复成原来的数字,返回最终的是元组;
n = tup[0]
# 第二次接受真实的数据
res = sk.recv(n)
print(res.decode())
# 第三次接受真实的数据
res = sk.recv(1024)
print(res.decode())
sk.close()

socketserver 
import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        print("handle方法被执行了...")
        
# ThreadingTCPServer(ip端口号,自定义的类)
server = socketserver.ThreadingTCPServer( ("127.0.0.1",9000) , MyServer )
# 建立连接,循环调用
server.serve_forever()  #表示该服务器在正常情况下将永远运行。

socketserver  用法
创建一个继承自socketserver.BaseRequestHandler的类;
这个类中必须定义一个名字为handle的方法,不能是别的名字!
将这个类,连同服务器的ip和端口,作为参数传递给ThreadingTCPServer()构造器
手动启动ThreadingTCPServer。

服务端套接字函数
s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数
s.connect()     主动初始化TCP服务器连接
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
(等价于:异常处理+connect 一旦网络不通,作用:返回错误号而不是直接报错)

公共用途的套接字函数
s.recv()            接收TCP数据
s.send()       发送TCP数据,send返回值是发送的[字节数量],这个值可能小于要发送的string字节数
s.sendall()    发送TCP数据,sendall返回值是None,发送string所有数据
'''
# 下面两个代码等价:
    #sendall => sock.sendall('Hello world\n')
    #send => buffer = 'Hello world\n'
             while buffer:
                n = sock.send(buffer)
                buffer = buffer[n:] (切片)
'''
s.recvfrom()        接收UDP数据
s.sendto()          发送UDP数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname()     当前套接字的地址
s.getsockopt()      返回指定套接字的参数
s.setsockopt()      设置指定套接字的参数
s.close()           关闭套接字

面向锁的套接字方法
s.setblocking()     设置套接字的阻塞与非阻塞模式
s.settimeout()      设置阻塞套接字操作的超时时间
s.gettimeout()      得到阻塞套接字操作的超时时间

面向文件的套接字的函数
s.fileno()          套接字的文件描述符
s.makefile()        创建一个与该套接字相关的文件

更多方法
#hashlib 这个模块是一堆加密算法的集合体,哈希算法的加密方式不止一种
https://www.cmd5.com/ md5解密
# 应用场景:在需要效验功能时使用
    用户密码的 => 加密,解密
    相关效验的 => 加密,解密

#哈希算法也叫摘要算法,相同的数据始终得到相同的输出,不同的数据得到不同的输出。
#(1)哈希将不可变的任意长度的数据,变成具有固定长度的唯一值    
 (2)字典的键和集合的值是通过哈希计算存储的,存储的数据是散列(无序)

进程的概念:(Process)

进程就是正在运行的程序,它是操作系统中,资源分配的最小单位.
资源分配:分配的是cpu和内存等物理资源
进程号是进程的唯一标识

同一个程序执行两次之后是两个进程
进程和进程之间的关系: 数据彼此隔离,通过socket通信

并行和并发
并发:一个cpu同一时间不停执行多个程序
并行:多个cpu同一时间不停执行多个程序

cpu的进程调度方法
# 先来先服务fcfs(first come first server):先来的先执行
# 短作业优先算法:分配的cpu多,先把短的算完
# 时间片轮转算法:每一个任务就执行一个时间片的时间.然后就执行其他的.
# 多级反馈队列算法

越是时间长的,cpu分配的资源越少,优先级靠后
越是时间短的,cpu分配的资源越多

进程三状态
(1)就绪(Ready)状态
    只剩下CPU需要执行外,其他所有资源都已分配完毕 称为就绪状态。
(2)执行(Running)状态
    cpu开始执行该进程时称为执行状态。
(3)阻塞(Blocked)状态
    由于等待某个事件发生而无法执行时,便是阻塞状态,cpu执行其他进程.例如,等待I/O完成input、申请缓冲区不能满足等等。

场景在多任务当中
同步:必须等我这件事干完了,你在干,只有一条主线,就是同步
异步:没等我这件事情干完,你就在干了,有两条主线,就是异步
阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行
非阻塞:没有任何等待,正常代码往下执行.
 
# 同步阻塞  :效率低,cpu利用不充分
# 异步阻塞  :比如socketserver,可以同时连接多个,但是彼此都有recv
# 同步非阻塞:没有类似input的代码,从上到下执行.默认的正常情况代码
# 异步非阻塞:效率是最高的,cpu过度充分,过度发热 液冷

#可以给子进程贴上守护进程的名字,该进程会随着主进程代码执行完毕而结束(为主进程守护)
(1)守护进程会在主进程代码执行结束后就终止
(2)守护进程内无法再开启子进程,否则抛出异常(了解)

********进程********
from multiprocessing import Process

linux 命令:
ps -aux 查看进程号
ps -aux | grep 2860
kill -9 2860  杀死进程

os.getpid()
获取当前进程id (子进程)

os.getppid()
获取当前进程id (父进程)

导入库:
from multiprocessing import Process

# 为了解决windows 和 linux 系统的兼容问题,下面这句话必须加上,否则报错
if __name__ == "__main__":
# 创建子进程,返回进程对象,执行func这个任务
p = Process(target=func)
p = Process(target=func,args=(n,)) # args=(n,)传递参数 args=后面只能是元组.  target表示调用的对象,就是子进程要执行的任务。
# 调用子进程 
p.start()       #启动进程
p.is_alive()  #判断进程是否是“活着”的状态。

# (4) 多个进程之间是异步并发
"""
多个进程之间是异步并发的程序,因为cpu的调度策略问题,不一定哪个任务先执行,哪个任务后执行.
整体而言,主进程比子进程创建的速度要快,cpu遇到阻塞会立刻切换任务,等到阻塞态的任务变成了就绪态,cpu再回来执行

主程序会默认等到所有的子程序执行结束之后,在统一关闭程序,释放资源.
若不等待,有可能在后台存有多个未执行结束的子进程,会变成僵尸进程,不停的占用cpu,内存
增加系统的压力,所有方便于对进程的管理,主进程默认等待子进程.

# (1) join 基本语法
.join 等待当前子进程全部执行完毕之后,主进程在执行(用来同步子父进程的)
p = Process(target=func)
p.join()

# ### 使用自定义类的方法创建进程
"""
自定义进程类的要求:
(1) 必须继承Process这个父类
(2) 所有进程执行任务的逻辑必须写在run方法里面
"""
class MyProcess(Process):
    def __init__(self,arg):
        # 手动调用一下父类的构造方法(最终实现进程的创建)
        super().__init__()
        self.arg = arg
if __name__ == "__main__":
    p = MyProcess("我是传进来的参数")
    p.start()
    print("3.子进程id>>{},4父进程id>>{}".format(os.getpid(),os.getppid()))
    """
    
# ### 守护进程
守护进程守护的是主进程,如果主进程中的所有代码执行完毕了,
当前这个守护进程会被立刻杀死,立刻终止.
进程对象.daemon = True 设置当前这个进程为守护进程  进程对象:例:p = Process(target=func)
必须写在start()调用进程之前进行设置

look

创建进程的时候,仍然是异步并发,
在执行到上锁时,多个进程之间变成了同步程序.
先来的先上锁,先执行,后来的进程后上锁,后执行
lock.acquire()# 上锁
lock.release()# 解锁

#同一时间允许一个进程上一把锁 就是Lock
    加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲速度却保证了数据安全。
#同一时间允许多个进程上多把锁 就是[信号量Semaphore]
    信号量是锁的变形: 实际实现是 计数器 + 锁,同时允许多个进程上锁

# 互斥锁Lock : 互斥锁就是进程的互相排斥,谁先抢到资源,谁就上锁改资源内容,为了保证数据的同步性
# 注意:多个锁一起上,不开锁,会造成死锁.上锁和解锁是一对.

look基本用法
from mulitprocessing import Process,Lock
look = Look() #创建锁 
look.acquire() #上锁  让程序先执行
look.release() #解锁  多个上锁,不解锁会造成死锁

with lock:
    data[0] += 1    使用with语法可以简化上锁和解锁两步操作

Semaphore 可以设置上锁的数量
同一时间最多允许几个进程上锁
创建进程的时候,是异步并发
执行任务的时候,遇到锁会变成同步程序.

Semaphore 基本用法
from multiprocessing import Semaphore,Process
sem = Semaphore(4) 控制上锁的数量
sem.acquire()  #上锁  让程序先执行
sem.release()  #解锁  多个上锁,不解锁会造成死锁

事件 (Event)
# 阻塞事件 :
    e = Event()生成事件对象e   
    e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
    # 如果是True  不加阻塞
    # 如果是False 加阻塞

# 控制这个属性的值
    # set()方法     将这个属性的值改成True
    # clear()方法   将这个属性的值改成False
    # is_set()方法  判断当前的属性是否为True  (默认上来是False)

Event 基本用法
from multiprocessing import Process,Event
e = Event()  #生成事件对象e
e.wait()       #动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
           # 如果是True  不加阻塞
          # 如果是False 加阻塞
# 控制这个属性的值
    # set()方法     将这个属性的值改成True
    # clear()方法   将这个属性的值改成False
    # is_set()方法  判断当前的属性是否为True  (默认上来是False)

# ### 1.进程队列
from multiprocessing import Process,Queue
"""队列特点: 先进先出,后进后出"""
q = Queue()    #创建队列
q.put(值)         #往队列中放值
q.get()            #获取值  队列中如果已经没有数据了,在调用get会发生阻塞.
q.get_nowait() #获取值  队列中如果已经没有数据了,直接抛出异常.
q.put_nowait()#超出队列长度后,直接报错
q2 = Queue(队列长度)   #设置队列长度

JoinableQueue 基本语法
from multiprocessing import Process, JoinableQueue
jq =JoinableQueue()  创建 为可join的队列
jq.put("a")          一次 内部的队列计数器加1
print(jq.get())     一次 通过task_done让队列计数器减1
# 通过task_done让队列计数器减1
q.task_done()    使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
q.join()                   生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止
print("finish")

Manager 基本语法
( list 列表 , dict 字典) 进程之间的共享数据(列表或者字典等)
from multiprocessing import Process,Manager,Lock
m = Manager() #创建共享数据对象
data = m.dict( {"count":20000} ) #创建一个字典
data = m.list( [1,2,3] )                 #创建一个列表

********线程********
from threading import Thread
进程:资源分配的最小单位
线程:cpu执行程序的最小单位
(1) 一个进程资源中可以包含多个线程
(2) 并发的多线程和多进程谁的速度快? 多线程!
(3) 多线程之间,共享同一份进程资源
t = Thread(target=func,args=(i,))      #target=fun 表示调func函数,args=(i,) 表示传进函数的参数,由元组组成
t.start()                                               # 启动线程
# ### 用类定义线程
线程.is_alive()    检测线程是否仍然存在
线程.setName()     设置线程名字
线程.getName()     获取线程名字
1.currentThread().ident 查看线程id号 
2.enumerate()        返回目前正在运行的线程列表
3.activeCount()      返回目前正在运行的线程数量
 用类定义线程 基本用法
from threading import Thread
class MyThread(Thread):
    def __init__(self,name):
        # 手动调用父类的构造方法
        super().__init__()
        self.name = name
    def run(self):
        print("当前进程号码是{},名字是{}".format(os.getpid() , self.name))

t = MyThread("当前是一个线程") #MyThread 是类的名字  ,"当前是一个线程" 是类的参数
t.start()

守护线程 : 
等待所有线程全部执行完毕之后,自己在终止,守护所有线程
setDaemon 守护线程 基本用法
t1.setDaemon(True) 在start调用之前,设置线程为守护线程

线程中安全问题 Lock
lock = Lock()  #创建一个锁对象 且只能在主进程里创建
from threading import Thread
from multiprocessing import Process,Lock
import time
n = 0
def func1(lock):
    global n
    with lock:
        for i in range(1000000):
            n += 1
def func2(lock):
    global n
    # with 自动完成上锁+解锁
    with lock:
        for i in range(1000000):
            n -= 1
if __name__ == "__main__":
    lst = []
    lock = Lock()
    startime = time.time()
    for i in range(10):
        t1 = Thread(target= func1,args=(lock,))
        t2 = Thread(target= func2,args=(lock,))
        t1.start()
        t2.start()
        lst.append(t1)
        lst.append(t2)
    for i in lst:
        i.join()   # 确保所有进程执行完毕之后,在向下执行,打印数据,否则报错.
    
    endtime = time.time()
    print("主线程执行结束 ...  打印{} 时间是{}".format(n,endtime-startime))
    
信号量 Semaphore (线程)
"""
再创建线程的时候是异步创建
在执行任务时,遇到Semaphore进行上锁,会变成同步程序
"""
sem = Semaphore(4) 控制上锁的数量
sem.acquire()  #上锁  让程序先执行
sem.release()  #解锁  多个上锁,不解锁会造成死锁

# ### 死锁 互斥锁 递归锁
"""只上锁不解锁是死锁"""
# (3) 递归锁的使用
from threading import Thread,RLock
noodle_lock = RLock()  #创建锁     用递归锁解决死锁现象

互斥锁    (尽量用一把锁解决问题) 
例子 :线程中安全问题 Lock

# ### 事件 Event
from threading import Event,Thread
e = Event()   #生成事件对象e
    # e.wait   动态添加阻塞
    # e.clear  将内部的阻塞值改成False
    # e.set    将内部的阻塞值改成True
    # e.is_set 获取内部的阻塞值状态(True False)

# ### 线程队列
from queue import Queue
put 存
get 取
put_nowait 存,超出了队列长度,报错
get_nowait 取,没数据的时,直接报错
linux windows 线程中 put_nowait get_nowait 都支持
PriorityQueue 按照优先级顺序进行排序(默认从小到大)

Queue()                 #先进先出,后进后出
q = Queue()           #创建队列

from queue import LifoQueue
LifoQueue              #先进后出,后进先出(栈的特点)
lq = LifoQueue(3)  #创建队列

from queue import PriorityQueue  
PriorityQueue              #按照优先级顺序进行排序(默认从小到大)
pq = PriorityQueue()  #创建队列

# ### 进程池和线程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
concurrent.futures 
为异步执行可调用对象提供了高层接口。进程池和线程池的出现是为了进程数或线程数限制在计算机可承受的范围内

ProcessPoolExecutor 进程池的基本使用 
os.cpu_count()  cpu逻辑核心数 即线程数
p = ProcessPoolExecutor()   #创建进程池对象括号里是线程数
res = p.submit(func,i)           #调用多进程任务(函数) fun:调用的函数   i:传递的参数
"""默认如果一个进程短时间内可以完成更多的任务,进程池就不会使用更多的进程来完成,以节省资源"""
res.result()                           #获取当前进程的任务的返回值(result获取任务返回值时,有阻塞)
p.shurtdown()                      #等待所有子进程执行结束之后,在继续执行主进程内容(shutdown)    p.shutdown()<===>p.join()  仅功能相似而已,不能调用

ThreadPoolExecutor 线程池的基本使用
from threading import current_thread  as cthread
tp = ThreadPoolExecutor()     # 创建线程池对象
"""参数: 默认并发的线程数 是 os.cpu_count() * 5 = 40"""
res = p.submit(func,i)           #调用多线程任务(函数) fun:调用的函数   i:传递的参数
"""默认如果一个线程短时间内可以完成更多的任务,线程池就不会使用更多的线程来完成,以节省资源"""
p.shurtdown()                      #等待所有子线程执行结束之后,在继续执行主进程内容(shutdown)    p.shutdown()<===>p.join()  仅功能相似而已,不能调用
res.result()                           #获取当前线程的任务的返回值(result获取任务返回值时,有阻塞)
cthread().ident                     # 获取线程id
线程池 map
from collections import Iterator,Iterable  Iterable可迭代性数据  Iterator迭代器
tp = ThreadPoolExecutor(5)  # 创建线程池对象(最大允许并发5个线程)
it = tp.map(func,range(3))     # 把执行的结果返回到迭代器中fun:调用的函数   range:传递的0-2d的参数
tp.shutdown()                       # 等待所有子线程执行结束.

# ###  回调函数
回调函数: 回头调用一下
    把函数当成一个参数传递给另外一个函数
    在当前函数执行完毕之后,最后调用一下当参数传递进来的函数    
    add_done_callback(回调函数)
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import current_thread  as cthread
import os,time
# (1) 进程池的回调函数: 由主进程执行调用完成的
def func1(i):
    print("process start ... " , os.getpid())
    time.sleep(1)
    print("process end ... ", i)
    return "*" * i
def call_back1(obj):
    print("<===回调函数callback进程号===>" , os.getpid())
    print(obj.result())

if __name__ == "__main__":
p = ProcessPoolExecutor()  #创建进程池对象
for i in range(1,11):              
    res = p.submit(func1,i)  #调用多线程任务(函数) fun:调用的函数   i:传递的参数
    # print(res.result())        #打印返回值
    res.add_done_callback(call_back1)  #在当前函数执行完毕之后,最后调用一下当参数传递进来的函数    
    # self.func(func2)                           #在当前函数执行完毕之后,最后调用一下当参数传递进来的函数    
p.shutdown()
print("主进程执行结束 ... " , os.getpid())
(2) 线程池的回调函数 : 由当前子线程调用完成的
def func2(i):
    print("thread start ... " , cthread().ident)
    time.sleep(1)
    print("thread end ... ", i)
    return "*" * i
def call_back2(obj):
    print("<===回调函数callback线程号===>" ,cthread().ident)
    print(obj.result())
if __name__ == "__main__":
    tp = ThreadPoolExecutor(5)
    for i in range(1,11):
        res = tp.submit(func2,i)
        res.add_done_callback(call_back2)
        
    tp.shutdown()
    print("主线程执行结束 ... " , cthread().ident)

Python协程(gevent模块)
协程的好处:
无需线程上下文切换的开销
无需原子操作(不会被线程调度机制打断的操作)锁定以及同步的开销
方便切换控制流,简化编程模型
高并发+高扩展性+低成文:一个CPU支持上完的协程都不是问题,所以很适合高并发处理

协程的缺点:
无法利用多核资源:协程的本质是单线程,需要和进程配合才能运行在多CPU上
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

协程的条件:
必须在只有一个单线程里实现并发
修改共享数据不需加锁
用户程序里自己保存多个控制流的上下文栈
一个协程遇到IO操作自动切换到其它协程

from gevent import monkey
monkey.patch_all())  #解决协程阻塞问题
import gevent
def eat():
    print("eat 1")
    time.sleep(3)
    print("eat 2")    
def play():
    print("play 1")
    time.sleep(3)
    print("play 2")
# 利用gevent.spawn创建协程对象g1
g1 = gevent.spawn(eat)
# 利用gevent.spawn创建协程对象g2
g2 = gevent.spawn(play)    
# 如果不加join阻塞,默认主线程执行时,不等待直接结束.
# 阻塞,必须等待g1协程任务执行完毕之后,放行
g1.join()
# 阻塞,必须等待g2协程任务执行完毕之后,放行
g2.join()
print("主线程执行结束 ... ")

************pymysql****************
# ### python 操作 mysql
import pymysql
'''setting -> pymysql'''

# ### 1.基本语法
"""
# (1) 创建连接  host  user  password  database 这四个参数必须写
conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826",charset="utf8",port=3306)
# (2) 创建游标对象(该对象可以操作数据库增删改查)
cursor = conn.cursor()
print(cursor)
# (3) 执行sql语句
sql = "select * from employee"
# 返回的是数据的总条数
res = cursor.execute(sql)
print(res)
# (4)获取数据 fetchone 获取一条
res = cursor.fetchone()
res = cursor.fetchone()
print(res)
# (5) 释放游标对象
cursor.close()
# (6) 关闭连接
conn.close()
"""
# ### 2.创建/删除 表
conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
cursor = conn.cursor()

# 1.创建一张表
sql = """
create table t1(
id int unsigned primary key auto_increment,
first_name char(10) not null,
last_name char(10) not null,
age int unsigned,
sex tinyint,
money float
)
"""

# res = cursor.execute(sql)
# print(res)

# 2.查看表结构
"""
sql = "desc t1"
res = cursor.execute(sql)
print(res) # 6条字段数据
print(cursor.fetchone())
print(cursor.fetchone())
print(cursor.fetchone())
print(cursor.fetchone())
print(cursor.fetchone())
print(cursor.fetchone())
"""

# 3.删除表
"""
try:
    sql = "drop table t1"
    res = cursor.execute(sql)
    print(res)
except:
    pass
"""
cursor.close()
conn.close()

# ### 3.事务处理
"""
pymysql 操作事务处理时,需要commit提交数据,才会变化,否则rollback回滚.恢复到最初状态
"""
conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
cursor = conn.cursor()
sql1 = "begin"
sql2 = "update employee set emp_name = '123egon' where id = 1"
sql3 = "commit"
res1 = cursor.execute(sql1)
res2 = cursor.execute(sql2)
res3 = cursor.execute(sql3)
# print(res1,res2,res3) # 返回值没有意义
# fetchone 与查询sql有关 , 增删改无效;
# tup = cursor.fetchone()
# print(tup)

cursor.close()
conn.close()

# ### sql 注入攻击

# 创建一张表
"""
create table usr_pwd(
id int unsigned primary key auto_increment,
username varchar(255) not null,
password varchar(255) not null
)
"""

# (1) sql注入的现象
"""
import pymysql
user = input("请输入用户名: >>> ").strip()
pwd = input("请输入密码: >>> ").strip()

conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
cursor = conn.cursor()

sql = "select * from usr_pwd where username='%s' and password='%s' " % (user,pwd)
print(sql)
res = cursor.execute(sql)
print(res) # 查询的条数

if res:
    print("登录成功")
else:
    print("登陆失败")

cursor.close()
conn.close()
"""

"""
输入时 : sfsdf' or 3=3 -- sdfsd
# -- 后面的字符串都会被注释掉, 前面账号虽然是错的 但是 2=2是真的 绕开了账号和密码的判断;
select * from usr_pwd where username='afasdfasdfasdf' or 2=2 -- sfasdf' and password='3434
"""

# (2) 使用预处理,提前对sql语句中的特殊符号进行处理
"""
使用预处理机制,可以避免绝大多数sql注入的问题
execute 如果参数为2个,将默认开启预处理
execute(sql , (参数1,参数2,参数3 .... ) )
"""

import pymysql
user = input("请输入用户名: >>> ").strip()
pwd = input("请输入密码: >>> ").strip()

conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
cursor = conn.cursor()
sql = "select * from usr_pwd where username=%s and password=%s"
res = cursor.execute(sql, (user,pwd) )

print("登陆成功" if res  else "登录失败")

cursor.close()
conn.close()

# ### python 操作mysql 增删改查
"""
    python 操作mysql时,默认开启事务,必须在增删改之后
    提交数据,才会真正对数据库发生变化,默认默认是回滚
    
    提交数据: conn.commit()
    回滚数据: conn.rollback()
    
    execute      一次插入一条
    executemany  一次插入多条

"""

import pymysql

# 1.创建mysql 链接
conn = pymysql.connect(host="127.0.0.1",user="root",password="123456",database="db0826")
# 查询数据,默认是元组,可以设置返回的类型为字典 pymysql.cursors.DictCursor
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # cursor=pymysql.cursors.DictCursor
"""
# 增
sql = "insert into t1(first_name,last_name,age,sex,money) values(%s,%s,%s,%s,%s)"

# 一次插入一条
res = cursor.execute(sql, ("宋","云杰",30,0,15000) )
print(res) # 1
# 获取最后插入这条数据的id号(针对单条数据插入)
print(cursor.lastrowid) # 3

res = cursor.executemany(  sql,  [  ("高","云峰",50,1,16000) , ("戈","隆",80,1,17000) , ("袁","伟倬",120,0,130000) , ("刘","欣慰",150,0,18000)   ]   )
print(res) # 插入的条数
# 针对于多条数据,搜最后的id 可以通过倒序查询id
sql = "select id from t1 order by id desc limit 1"
res = cursor.execute(sql)
print(res)
# 获取最后一个id号
res = cursor.fetchone()
print(res)
"""

# 删
"""
sql = "delete from t1 where id = %s"
res = cursor.execute(sql , (3,))
print(res)
if res:    
    print("删除成功")
else:
    print("删除失败")
"""

# 改
"""
sql = "update t1 set first_name = %s where id = %s"
res = cursor.execute(sql,("王",4))
print(res)

if res:
    print("修改成功")
else:
    print("修改失败")
"""

# 查
"""
fetchone  fetchmany fetchall 都是基于上一条数据往下查询.
"""
sql = "select * from t1"
res = cursor.execute(sql)
print(res) # 总条数

# (1) 获取一条数据 fetchone
# {'id': 4, 'first_name': '王', 'last_name': '云杰', 'age': 30, 'sex': 0, 'money': 15000.0}
res = cursor.fetchone()
print(res)

# (2) 获取多条数据 fetchmany
data = cursor.fetchmany() # 默认搜索的的是一条数据
print(data)
data = cursor.fetchmany(3)
print(data)

"""
[
{'id': 6, 'first_name': '高', 'last_name': '云峰', 'age': 50, 'sex': 1, 'money': 16000.0}, 
{'id': 7, 'first_name': '戈', 'last_name': '隆', 'age': 80, 'sex': 1, 'money': 17000.0}, 
{'id': 8, 'first_name': '袁', 'last_name': '伟倬', 'age': 120, 'sex': 0, 'money': 130000.0}
]
"""

for row in data :
    # print(row)
    first_name = row["first_name"]
    last_name = row["last_name"]
    age = row["age"]
    if row["sex"] == 0:
        sex = "女性"
    else:
        sex = "男性"
    
    money = row["money"]
    print("姓:{},名:{},年龄:{},姓名:{},收入:{}".format(first_name,last_name,age,sex,money)  )

# (3) 获取所有数据 fetchall
"""
data = cursor.fetchall()
print(data)
"""
# (4) 自定义搜索查询的位置

sql = "select * from t1 where id >= 20"
res = cursor.execute(sql)
print(res)
"""
# 1.相对滚动 (正数相对于当前位置往后滚,负数反之.)
cursor.scroll(3,mode="relative")
res = cursor.fetchone()
print(res)

cursor.scroll(3,mode="relative")
res = cursor.fetchone()
print(res)

# 27 往前滚
cursor.scroll(-2,mode="relative")
res = cursor.fetchone()
print(res)
"""

# 2.绝对滚动 , 永远基于第一条数据的位置进行移动
cursor.scroll(0,mode="absolute")
print(cursor.fetchone())

cursor.scroll(1,mode="absolute")
print(cursor.fetchone())

cursor.scroll(3,mode="absolute")
print(cursor.fetchone())

# 往前滚没有数据,超出范围error
"""
cursor.scroll(-1,mode="absolute")
print(cursor.fetchone())
"""

# 在进行增删改查时,必须提交数据,才会产生影响.
conn.commit()
cursor.close()
conn.close()

# 导出数据库
第一步: 先退出数据库
第二部: 切换到对应的路径
mysqldump -uroot -p db0824 > db0824.sql
第三部:
    # 导出所有内容
    mysqldump -uroot -p db0824 > db0824.sql
    # 导出单个表
    mysqldump -uroot -p db0824 t1 > t1.sql
    
# 导入数据库
第一步 : 先创建一个空的数据库
第二部 : 找到sql对应文件目录
第三部 : source 路径/文件
    use 数据库
    source D:\db0824.sql

python 基础词汇及其应用1相关推荐

  1. python基础知识-python基础知识,python必背内容,一、python的基

    python基础知识,python必背内容,一.python的基 一.python的基础 1.简单写一行python代码:print("hello,world')print("你好 ...

  2. 精品课 - Python 基础

    个人简历 王圣元 (FRM, CAIA) 新加坡某金融咨询公司总监 新加坡国立大学金融数学硕士 新加坡国立大学量化金融学士 <快乐机器学习>的作者 <Python - 金工, 机学, ...

  3. 小白都能学会的Python基础 第六讲:综合实战2 - 大数据分词与词云图绘制

    1.华小智系列 - Python基础(案例版) <Python基础>目录 第六讲:综合实战2 - 大数据分词与词云图绘制 1.大数据分词技巧 2.词频统计技巧 3.词云图绘制 4.微博词云 ...

  4. python基础大满贯——20170423

    时间:2017-04-23 地址:沙河城铁a1口右转右转直走--汇德商厦401 python基础回顾 一.语言分类 c语言:机器码 其他高级语言:字节码--机器码 -python语言分类 cpytho ...

  5. python基础模型_零基础python代码策略模型实战

    内容摘要 1 本文概述 本文主要介绍了python基础.爬虫.与数据库交互.调用机器学习.深度学习.NLP等.分别介绍了各个模块的安装,环境的搭建等.并且以机器学习选股为例,把各个模块连贯起来,核心代 ...

  6. python基础入门01

    python 基础入门01 前言 python 是一种计算机程序设计语言, 由创始人吉多·范罗苏姆(Guido van Rossum) 在1989年阿姆斯特丹的圣诞节期间为了打发无聊的时间,决定开发一 ...

  7. python基础四_01_面向对象

    python基础四_01_面向对象编程 导读: 本文主要从what?why?how?三个方向理解面向对象编程的思想:仅供自己梳理. 一.什么是面向对象编程? 面向对象编程与面向过程编程是两种常见的编程 ...

  8. python基础知识测试题_Python中的单元测试—基础知识

    python基础知识测试题 Unit testing is the number one skill which separates people who just finished their de ...

  9. python基础笔记,超详细,包含面向对象基础,爬虫实战【持续更新中...】

    前言: 本笔记中的函数和方法同义,面向python3 本笔记部分概念及代码由newbing搜集整理得出 本笔记适合有一定其他编程语言基础的同学,因为笔记中省略了部分基础概念(比如整型,浮点型等基本数据 ...

最新文章

  1. java集合类讲解视频,关于java:实实在在面试List和Map集合面试合集含讲解视频
  2. CDH5离线安装手册
  3. 学习笔记Hadoop(一)—— Hadoop介绍(1)——认识大数据
  4. GPT v.s. 中国象棋:写过文章解过题,要不再来下盘棋?
  5. CCF2016.4 - A题
  6. 如何用最短的时间学会C语言,并掌握C语言的精髓所在?
  7. xxljob 配置具体定时任务_记一次xxl-job定时任务没有触发的问题
  8. 【Immutable】拷贝与JSON.parse(JSON.stringify()),深度比较相等与underscore.isEqual(),性能比较...
  9. 4步教你玩转可视化大屏设计|内附实际操作
  10. SAP License:FM-基金管理详解(实例)
  11. php中声明空数组,总结PHP中初始化空数组的最佳方法
  12. linux查看cpu、内存、版本信息
  13. redhat multipath配置文件简要说明
  14. matlab三维热传导计算,matlab练习程序(差分法解二维热传导方程)
  15. Arduino 入门学习9 OpenBlock 可视化开发工具环境搭建
  16. html怎么设置文字无法复制粘贴,网页文字无法复制粘贴怎么办
  17. android 程序闪退 log,应用闪退log日志。。
  18. 九九乘法c语言的编程,C语言九九乘法表
  19. 用Java解决牛客网题目BC30kiki和酸奶
  20. 超简单集成华为HMS Core MLKit 机器学习服务银行卡识别SDK,一键实现银行卡绑定

热门文章

  1. GCT备考之考前辅导篇
  2. 第八篇order订单专题(4)市价单、收盘价单、限价单、止损单
  3. iOS开发 - 新特性的坑之应用字体根据系统字体大小而变化
  4. php 读取 wps,php Word成功转PDF(wps/microsoft word)
  5. OpenWrt各大软件源地址
  6. 解决: This Python interpreter is in a conda environment, but the environment has not been activat
  7. 样本方差公式推导--为什么样本方差的分母是n-1
  8. 组织中的各种架构师分类
  9. Vue 用户登入及token 认证
  10. 读易[5]·做鸡头还是凤尾(小过卦)