目录:
一、基本结构
二、变量和数据类型
三、列表,元组,字典的增删改查
四、各种函数
五、各种循环(迭代器和生成器)
六、类和实例
七、异常
八、模块(进程和线程)
九、
十、
正文部分:
一、基本结构:
-
#-*- coding=utf-8 -*-
使python2可以识别中文字符 - python2中的输入: raw-input:保留输入的格式,比如1+10只能用这个,用input会变成11
- print(‘xxxx’,end=’’)`输出可以不换行,参数为end=‘’
- print(’’)换行
- \t 末尾单词首字母与下一个单词之间加入一个tab的空隙
- python 里的赋值操作实际上是引用,a=b,并不是用b赋值a,而是用b的值的地址给a引用一份,当b的值改变,a的也会改变。
- 可变类型:列表 ,字典
不可变类型:元组,字符串,数字
key一定是不可变类型 - input(’’):输入的一定是str,可用int()转换成数字,eval转换成函数(eval其实是还原之前类型),float转换成小数
- ——+=——和=——+——不一样,前者是修改当前引用的值,后者是引用新值
- 浅拷贝: 即复制原文件的第一层,对内部增加一个引用
深拷贝:完全复制原文件,指向新文件copy.deepcopy()
copy.copy():只拷贝一层即,且,copy可以判断是否是可变对象,不可变对象只会生成新的引用
详细解析:
关于’=‘
a=[1,2,[3,4]]
b=a
a.append(5)
print(a)=[1,2,[3,4],5]
print(b)=[1,2,[3,4],5]
"="是完全的新建一个引用
浅拷贝:
import copy
a=[1,2,[3,4]]
b=copy.copy(a)
a.append(5)
print(a)=[1,2,[3,4],5]
print(b)=[1,2,[3,4],]
此时第一层复制是复制了内容的
import copy
a=[1,2,[3,4]]
b=copy.copy(a)
a[2].append(5)
print(a)=[1,2,[3,4,5]]
print(b)=[1,2,[3,4,5]]
对于列表里面包含的列表并未复制,而是建立了一个引用。
深拷贝:
import copy
a=[1,2,[3,4]]
b=copy.deepcopy(a)
a[2].append(5)
print(a)=[1,2,[3,4,5]]
print(b)=[1,2,[3,4]]
完全复制为两个独立文件
- 二进制:bin() 0b 八进制:oct() 0o 十六进制:hex()
0x
常见于某些神秘代码抬头----0x - 原码and反码
- 位算:
按位与& 两数都为1的位,取1,其余为0
按位或| 两数只要有1的位,取1,其余为0
按位异或^ 两数相同的位取1,其余取0
取反~ 0取1,1取0
二、数据类型
- str的部分方法:
1、find从左边找第一个,rfind从右边找第一个
index同理
2、.count 统计出现次数
3、.replace(’’,’’,需要替换的个数)替换
4、split 切割(按空格)
splitline 按行切割
5、capitalize 句首字母大写
6、title 每个单词首字母大写
7、endwith/startwith 判断是否以()结尾/开头
8、lower/upper 小写化/大写化
9、ljust,rjust,center 居左/右/中显示,括号里为总长度
10、lstrip,rstrip,strip 清除左,右,全部空格
11、patition,rpatition,以```为分界点
12、isalnum,isalpha,isdigit,isspace判断是否含有数字,纯字母,纯数字,纯空格
13、join
例:a=[‘fgf’,‘dwd’,‘fff’] b=’ ’
b.join(a)=‘fgf dwd fff’
三、列表、元组和字典的增删改查
- 列表[ ]方法:*
1、extend:末尾拓展,注意:如果是添加一个单元素列表的话,会直接整体添加进去,此时直接用+解决。
2、insert(位置,内容):指定位置插入
3、append 末尾t添加(末尾添加一个整体),append的项会作为一个整体,且xxx.append()单独执行就会产生效果,不能再赋值。
4、pop 末尾删除元素
5、remove 删除指定元素(元素名称,且只删一个)
6、del 根据下标删除
7、赋值操作可以改变列表的某些项
8、in 查询是否在列表
9、.sort 排序,默认从大到小
10、列表生成式
[i for i in range(10) if i %2==0] 数字规则,顾前不顾后
11、列表去重:
list1 = [1,2,3,2,0]
temp = list1[:]
list1.clear()
for each in temp:
if each not in list1:
list1.append(each)
print(temp)
print(list1)
- dict {}方法:
1、xxx.get(key,value) 增加key 和vlue
2、xxx.pop(key) 删除指定key及其value
3、xxx[key] 查找key对应的value,也可以赋值
4、xxx.keys () 查询key
5、xxx.values() 查找value
6、xxx.items() 输出一个列表,把key和value一一对应封装到元组中
集合{}:value=none的字典,特点是元素不重复。
集合{}:只含有key的字典。
集合与之前列表、元组类似,可以存储多个数据,但是这些数据是不重复的
集合对象还支持union(联合|), intersection(交&), difference(差-)和sysmmetric_difference(对称差集^)等数学运算.
- 元组()方法:不支持修改,但是可以用赋值同名变量操作覆盖修改
四、各种函数
- def 函数:
运行到return函数结束,此效果优先生效于循环 - 关于参数的一些说明:
实参: 实实在在传入的参数
形参:占位参数,表示需要传入参数值
global 将局部变量申明为全局变量
args: 以元组传入参数
**kwargs: 以字典方式传入的参数
注:关键点是和**,而不是字母,用这几个称呼只是约定俗成。在已有元组和字典形参的情况下,调用参数时也可以直接用*和**标记,表示用元组或者字典方式处理,否则,单独传入字典或者列表的情况下,会被当作一个整体,作为元组的一个元素处理。 - id() 显示对象内存地址,物理地址
- readline 读取数据一行
readlines 一次性读取每行作为列表的一个元素方式
read 读取字节
seek(,【0,1,2】) 设定指针位置,前面是微调,后面0是开头,1是中间,2是末尾 - open函数:
r+具有读写属性,从文件头开始写,保留原文件中没有被覆盖的内容;
w+具有读写属性,写的时候如果文件存在,会被清空,从头开始写。
r 打开只读文件,该文件必须存在。
r+ 打开可读写的文件,该文件必须存在。
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。
五、各种循环
1.循环中删除项可能会引起漏项`
a=[1,2,3,4,5]
for i in a:
print(i)
if i ==22:
a.remove (i)
结果:
【1,2,4,5】
因为列表浏览是靠指针的,当null扫描到2时,删除了2,3替补到了2的位置,null,从原2,现3的位置的下一位,继续扫。
同理,当连续判断两个相邻位置是否可以删除时,有可能会出现漏删。
2.可迭代路线:
以直接作用于 for 循环的数据类型有以下几种:
一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
一类是 generator ,包括生成器和带 yield 的generator function。
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable
isinstance(实例,类型)判断实例是否是该类型
生成器:
- 产生原因,在用列表生成式等一次性生成工具的时候,有可能需要内存太大,所以出现了替代品,每当需要新值时就运算一次,生成下一个值。
- 创建格式将列表生成式的最外围【】改成()或者 在循环中加入yield。
-
next(a)=a.__next__()
等价,a.send(‘str’),可将str 赋值给yield语句,并且相当于运行一次next。
迭代器:可以用next()函数输出下一个值的对象,iter() 生成迭代器
- iter()把可迭代对象 生成迭代器
六、类和实例
type可以创建类
type(类名,(父类名),{方法名:值或者外部的某个函数})
types.MethodType(函数名,对象名):给函数绑定对象
元类:一切皆对象,创建类的类,type就是一切类的元类,有一个__metaclass__属性,可以手动创建类,但是如果没有外部定义的话,就会使用type来创建。除了type,一切皆对象,不是类的实体,就是元类的实体。
类属性:在类中直接定义的属性,会赋予到实例中去。
私有属性:属性前加__,不可被外界调,但是可以被类方法调用,注意,一般放在__init__函数里,但是单独放出了也是一样的,这个私有属性的实质是变更了函数名字,要想在外部调用的话,需要输入完整的名字,完整名字为:_类名__属性
私有化:
xx: 公有变量
_x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,但是import模块整体后是可以导入的,类对象和子类可以访问
__xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)
__xx__:双前后下划线,用户名字空间的魔法对象或属性。例如:__init__ , __ 不要自己发明这样的名字
xx_:单后置下划线,用于避免与Python关键词的冲突
闭包:在函数中定义新函数,并且新函数引用了外部函数的变量。且要return新函数
装饰器:原理是
def w1(func):
def inner():
插入位置
func()
return inner
def f1():
pass
w1(f1)==f1
但是在上面的这个过程中可以插入很多不一样的东西,且装饰器其实是将函数作为变量传入到另一个装饰函数中。
装饰方式是在函数上方加上@
双装饰器:
@w1
@w2
function()
实际上是相当于:w1(w2(f)),装饰流程是先2再1,运行流程上先1再2,但是如果遇到调用f的1时候,2会在里层
装饰时的顺序是先w2再w1,生效的顺序是先w1再w2.
装饰器生效时间:运行时已经装饰,而不是调用的时候
被修饰的函数中的return,返回值是返回到装饰函数里,而不是最外层。
通用装饰器:自带返回值和不定参数(*args,**kwargs),可以适配各种不同的函数
装饰器也可以带参数,直接用括号接在@函数名后面
return
return如果返回的是一个函数的话,就不需要加(),函数名即可,如果返回的是函数的值的话,就需要加括号和参数。
property方法:
私有变量名(不含__)=property(方法名,方法名)
使得私有属性的方法可以和实例属性一样的方式被调用,将方法封装起来。且get方法必须在前面,set方法在后面。
注:也可作为装饰器,此时函数名和变量名一致,是加在get方法上,用@加在函数上方一行,而set方法也需要用装饰器 @函数名setter
标记出来。
类的方法:
`__del__`方法:对象消失的时候被调用
`__new__`方法:创建对象的方法,调用父类的new方法而不是子类的(内置于类建立的时候)
`__str__`方法:打印的时候调用,return打印的结果
`sys.getrefcount()` 计算引用次数,调用此函数本身也算一次
`__name__`:一个特殊的私有变量,在模块中,如果是直接被python3调用所在模块,会输出`__main__`,如果是被其他模块调用所在模块,会输出自身所在模块名字。
`__all__`:格式是`__all__`=['函数名'],表示此模块中只授权可调用该函数
__slots__
:限定属性类型,例如:__slots__=('name','age')
此类的属性只能有name和age
类的继承:
class xxx(父类)
子类的同名方法会在子类的引用中覆盖父类方法,但是用父类名字执行方法时,仍然可以调用父类方法或者用super().
也可以调用父类方法。
私有方法和属性不会被继承
mro:按被调用顺序依次打印对象所属类
多态:同一个函数,对于处于不同类的对象,可以不同的结果
面向对象的三要素:封装,继承,多态
耦合关系:子类与基类关联性,即子类改变也会牵动父类改变
简单工厂模式: 通过构建中继类把基类和子类解藕,
工厂方法模式: 父类的功能在子类中实现
引用其他类的方法:`类().方法()
七、异常管理:
try
‘’’’’’
except xxxx:
或
except yyyyy as 任意参数:
【输出错误类型】
else【选择执行】:
finally【一定会执行】:
注:exception是所有异常的统称
八、模块:
1、import载入模块(导入模块的实质是把模块中所有程序执行一遍):
- import
- import as
- from xxx import yyyyy
2、os模块:
listdir:获取目录中的文件名
rename:重命名
chdir:改变当前目录
getcwd 获取当前文件的储存路径
__file__ :显示os模块所在路径
fork():
程序执行到os.fork()时,操作系统会创建一个新的进程(子进程),然后复制父进程的所有信息到子进程中
然后父进程和子进程都会从fork()函数中得到一个返回值,在子进程中这个值一定是0,而父进程中是子进程的 id号
import os
import time
rpt=os.fork()
print('hhh')
if rpt==0:
while True:
print('---1---')
time.sleep(1)
else:
while True:
print('---2---')
time.sleep(1)
在Unix/Linux操作系统中,提供了一个fork()系统函数,它非常特殊。
普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回子进程的ID。
这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。
getpid()、getppid():打印本程序id,打印父进程id
不同进程之间全局变量不共享
ubuntu终端里,是否打印下一句系统命令是有父进程结束决定的,所以会出现以下情况
sam@ubuntufuben:~/桌面/pythonfile$ python3 a.py
emmmmmmm
我是父进程
emmmmmmm
我是子进程
sam@ubuntufuben:~/桌面/pythonfile$ hhhhh,我还没死
fork炸弹:
即while True:
fork()
3、mutiprocessing:
Process用作创建新进程。
Process(target=)
Pocess语法结构如下:
Process([group [ target [ name [args [kwargs]]]]])
target:表示这个进程实例所调用对象;
args:表示调用对象的位置参数元组;
kwargs:表示调用对象的关键字参数字典;
name:为当前进程实例的别名;
group:大多数情况下用不到;
Process类常用方法
is_alive():判断进程实例是否还在执行;
join([timeout]):完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止,可以添加数字,即主进程结束秒数;
start():启动进程实例(创建子进程),启动target;
run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法;
terminate():不管任务是否完成,立即终止;
Process类常用属性:
name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数;
pid:当前进程实例的PID值;
Process是一个1类,可以创建子类的创建进程
Pool进程池:
pool主进程结束并终止了,子进程也没了,所以也要用join()【所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止】
使用方式:
duixiang = Pool(进程数)
duixiang.apply_async(需要执行的函数,需要给函数传入的参数,其他)
特别的
pool.apply_async(func=test,callback=test2),此时当子进程执行完test以后,主进程会执行call back,这是异步。
Queue(先入先出),LifoQueue(后进先出):
q=Queue(数字或不填)【要是用pool中的进程通信的话,要使用manager().Queue()】
队列,进程件通讯。可以新建一个队列,有put,get,qsize,full,empty,等方法。
put,get是堵塞式的,即取完以后不会出错,而是等待进一步动作
put_nowait,get_nowait 非堵塞式的,取完以后会报错。
多进程的所有数据都是隔离的,
Threading模块:
和Process很像,但是不用加join也会有堵塞的效果,使用方式也一致
q=Thread(target=,())
也是用start()开启进程
线程共享全局变量,其余不共享。
current_threading():输出执行进程的对象,可以用name方法输出名字。
定义的不同
进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
区别
一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
线线程不能够独立执行,必须依存在进程中
优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。
线程同步:即不同线程协同改变同一个变量,而且要使得这个过程正确有序执行。
出现不同步的情况是因为,cpu一次性可能不会执行完一个完整语句结构,导致但是同一个变量在两个线程都已经载入了,此时两个变化有可能会重叠
避免修改在线程执行时被其他线程修改全局变量的方法:
1、轮询,不断的判断语句的搁置其他线程的进行,使得全局变量在某一线程中可以完整的执行。效率低
2、互斥锁,threading的Lock()。一旦上锁,就会导致其他线程堵塞,直到解锁。通知模式,即只是完成后通知一次,效率高
new_Lock=Lock() 新建锁
new_Lock.acquire()上锁
new_Lock.release()解锁
if 语句的lock会直接锁上,并往下执行
threading.local():新建一个全局变量,可以用字典方式储存各线程返回的值,当线程调用这个对象时,只会调用它自己有关的值。
socket模块:套接字socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的
例如我们每天浏览网页、QQ 聊天、收发 email 等等
tcp
udp 快但是不稳定
创建一个tcp socket(tcp套接字)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket Created'
创建一个udp socket(udp套接字)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print 'Socket Created'
数据发送
udp模式:特别注意地址的选择
from socket import *
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 准备接收方的地址,每次发送都要写
sendAddr = (‘192.168.1.103’, 8080)
#3. 从键盘获取数据
sendData = raw_input(“请输入要发送的数据:”)
#4. 发送数据到指定的电脑上
udpSocket.sendto(sendData, sendAddr)
#5. 关闭套接字
udpSocket.close()
sys模块:
argv方法:允许在程序外输入参数,即命令行参数
pygame模块:
这里是引用
[外链图片转存失败(img-wDApJ2PJ-1563952540784)(https://screenshotscdn.firefoxusercontent.com/images/65b2df4c-8159-43c3-b1c0-d02a9d1f7737.png)]pygame模块里,display.update必须位于对象的display之后
包:
在文件夹中新建__init__.py文件,此文件夹会被认为是包.(python2应用,python3不需要),在__init__.py文件中可以输入__all__限制此包可调用的文件,也可以用import载入包中文件格式是: from . import xxx(此格式python2,3通用) 。
发布模块:
材料:一个含有可运行py文件的文件夹,文件夹内部有一个__init__.py文件,文件夹同级目录中有一个setup.py文件,代码为:
from distutils.core import setup
setup(name="名字", version="版本号", description="描述", author="作者", py_modules=[内容物'])
内容物的形式一定是: 文件夹名.不加后缀名的文件名 形式
且是字符串
代码:
python3 setup.py build 建立模块
python3 setup.py sdist 打包
后续待添加内容:几个项目代码,网络部分等等