一、操作系统相关知识
操作系统
- 内存管理
- 驱动管理
- 进程线程协程
- 文件系统
1、内存
32位电脑 4G
DOS 内存是程序自己控制
Windows 统一的内存空间 4G
虚拟存储器:
(1) CPU n核心 ALU cpu寄存器
(2) 每个核心 L1 L2 cache miss
(3). 整个CPu L3 3M
(4) 内存 很大很大8G
(5)硬盘
(6) 网络传输
2、 驱动
ps/2 usb bluetooth
flopy disk
linux: 统一成文件 read write seek
3、 文件系统
数组
[meta元信息 对应的文件位置(偏移量) 对应的文件大小]
格式化: 会把所有信息抹掉
快速格式化:meta清空
所有的文件存在同一个file
/main/main.py -> file load -> execute
4、进程线程
进程间通信:pipe file socket
线程通信:对n个线程来说,每个线程都可以看到该进程中的全局数据
区别:
对于一个进程来说,你持有了一个页表
对于同一个进程内的线程,你共享同一张页表
5、并发与并行
并发:不管你多少个线程,只要你系统能处理多个事情,就是并发的
并行:这些事情都是在同一时间执行的 多线程 多进程
6、同步异步
同步:事件发生与否,需要你自己去检查
异步:事件的发生与否,这个是别人通知给你的
7、阻塞非阻塞
阻塞需要等
不等,就是非阻塞
8、编译 解释 JIT
编译:一个代码编译成另外一种代码,编译到机器码,目标代码就是机器码
解释: c语言是统一的,那我用c语言写出一个虚拟机,这个机器是可以部署到任何机器的python语言,语言逐条转换成对应的虚拟机指令
JIT:把最热的代码替换成编译到机器码
9、动态语言和静态语言
动态语言:像python一样可以赋值不同类型的数据
a = ''
a = 1
a = True
静态语言:只能赋值指定类型的数据
二、python高级语法
1、深拷贝、浅拷贝
python中的引用类型:[],{}
深拷贝:
l2深拷贝了l1,l1添加了1,l2不会变。l2是一个新的地址,l2和l1是两个独立的变量
from copy import deepcopy
l1 = []
l2 = deepcopy(l1)
l1.append(1)
print(l2)
l1 = [1, [1, 2], 3]
l2 = l1[:]
浅拷贝:
l2浅拷贝了l1,当l1中变化时,l2也跟着变。因为l2只是引用了l1的地址,自己并没有申请到内存
l1=[]
l2=l1
l1.append(1)
print(l2)
**默认参数的陷阱:**下面也是引用类型,第一次a=[]创建变量,第二次是引用了之前的a,所以第一次只输出[1],第二次输出[1,1]
def foo(a=[]):
a.append(1)
print(a)
foo()
foo()
2、lambda
相当于单参数函数,输入参数是x,输出x+1
lambda x : x+1
map(表达式,[数据]):对数组中所有数据进行表达式运算
filter(表达式,数据):对所有数据筛选出符合条件的数据
functools.reduce(function,sequence,initial)对sequence队列进行function操作,初值是initial(从5开始加1.2.3.4.5=20)
import functools
import operator
mul2 = lambda x: 2 * x
print(mul2(3))
print(list(map(lambda x: 3 * x, [1, 2, 3, 4])))
print(list(filter(lambda x: x % 3 == 0, [1, 2, 3, 4])))
print(functools.reduce(operator.add, [1, 2, 3, 4, 5], 5))
输出:
6 [3, 6, 9, 12] [3] 20
3、args kwargs
可以输入任何形式的参数
args表示元组形:(a,b,c,d)
kwargs表示字典形式:k=v
def log(*args, **kwargs):
print("args", args)
print("kwargs", kwargs)
log(1, 2, 3, 4)
log(1, 2, [1, 2, 3], c=4)
输出:
args (1, 2, 3, 4)
kwargs {}
args (1, 2, [1, 2, 3])
kwargs {'c': 4}
4、closure
闭包
输出是welcome akira
def greeting(msg):
def hello(name):
print(msg, name)
return hello
h = greeting("welcome")
h("akira")
陷阱:
l = []
for i in range(10):
def _():
print(i)
l.append(_)
for f in l:
f()
输出10个9,因为在f()运行的时候才开始找i,而此时的i已经迭代到9了,所以调用时都是9(闭包引用)
解决方法:
默认参数=外部引用,每次都进行拷贝,不能算是闭包了,能输出0-9
l = []
for i in range(10):
def _(i=i):
print(i)
l.append(_)
for f in l:
f()
5、迭代器iterator
(a)循环体
for i in range(10):
pass
(b)拥有起始、循环、跳出条件(和c语言一样)
1、 iter: iter(obj) = obj.iter()
2.、next :next(obj) = obj.next()
class Pow2(object):
def __init__(self, max):
self.max = max
self.n = 0
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n < self.max:
self.n += 1
return 2 ** self.n
else:
raise StopIteration
p = Pow2(10)
for i in p:
print(i)
6、类方法、实例方法、静态方法
(1)实例方法,绑定在实例对象self上
class A(object):
def foo(self):
pass
a = A()
a.foo()
(2)类方法,绑定在类clf上
class A(object):
@classmethod
def c_foo(cls):
pass
A.c_foo()
(3)static method
就和普通在类外面的函数一样和类之间没有关系,如果这个方法只能在该类中使用,就加上@staticmethod
可以用A.s_foo() ,只是不会把类传进去
class A(object):
@staticmethod
def s_foo():
pass
@classmethod
def c_foo(cls):
pass
def foo(self):
pass
a = A()
a.foo()
A.c_foo()
7、decorator(AOP编程)
对函数的装饰器,测试代码和发布代码不一样,发布时的代码可以隐藏测试时候的代码
包装后返回函数对象,在里面可以插入其他代码,这样可以同时在很多函数中插入同样的代码
def simple_wrapper(fn):
def _():
print(fn.__name__) #这个就是插入的代码
return fn()
return _
@simple_wrapper
def foo():
pass
@simple_wrapper
def bar():
pass
foo()
bar()
做一个可以传入很多参数的万能函数,但是不可以有默认参数
def all_args_wrapper(fn):
def _(*args, **kwargs):
print(*args, **kwargs) #插入的函数
return fn(*args, **kwargs)
return _
@all_args_wrapper
def bar(a,b,c):
pass
bar(1,2,3)
8、列表、字典递推式
(1)list comprehension(列表会占用很多内存空间)
[i for i in range(10)]
(2)dict comprehension
{k:1 for k in range(10)}
(3)list generator
(i for i in range(10))
9、magic method魔法方法
__xxx__为魔法方法,外部不可见
(1)getattribute
访问类里面任何一个属性的时候都会调用getattribute方法
class LogAll(object):
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def __getattribute__(self, item):
print(item)
l = LogAll()
print(l.a)
l.a = 1
l.b
l.c
(2)getattr和setattr
missing method:
getattr:当类的实例调用的方法在类中没有时,会自动执行该方法
setattr:不仅在类中没有时执行,并且还可以给属性赋值操作
class Any(object):
def __getattr__(self, item):
print(item)
def __setattr__(self, key, value):
print("set", key, value)
a = Any()
a.a
a.a = 1
输出:
a
set a 1
可以自动生成类中没有的函数,并传入任意参数(*args, **kwargs)
class Any(object):
def __getattr__(self, item):
def _(*args, **kwargs):
print("function name", item)
print("args", args)
print("kwargs", kwargs)
setattr(self, item, _) #获得没有的函数时set一下,以后再调用时就不需要执行getattr了
return _
a = Any()
a.fuck(1, 2, 3)
a.shit(1, 2, [1, 2, 3], c=[])
输出:
function name fuck
args (1, 2, 3)
kwargs {}
function name shit
args (1, 2, [1, 2, 3])
kwargs {'c': []}
10.mixin
解决类之间相互引用、相互依赖:把多个类mix到一起(继承多个类)——小范围使用
类A和类B里面的方法相互调用,利用第三个类C,继承A,B,C中调用方法即可
下面是A中的函数调用了B中的shit函数,C继承自A和B,在C中执行A中的函数,即可成功调用到B中的函数
class A(object):
def foo(self):
print("foo")
def bar(self):
print("bar")
self.shit()
class B(object):
def shit(self):
print("shit")
class C(A, B):
pass
c = C()
c.bar()
三、python语法细节
1、将字符串与数值进行拼接,需要将数值转换成字符串,用str()、repr()函数
2、input函数获取用户输入,input()返回字符串
3、单双引号可以 交替使用,字符串中有单引号,就可以用双引号包含此字符串
4、对长字符串可以用()对换行符进行转移,可以换成两行
5、原始字符串以“r”开头,不会对引号中的特殊字符进行转义,r'G:\publish\code'
6、字符串改成字节(二进制)数据:如果字符串都是ASCII字符,则在字符串前面添加b;
用bytes(‘xxxxx’)将字符串转成bytes对象,且使用utf-8编码b=bytes("学习",encoding='utf-8')
或者b="学习".encode('utf-8')
解码使用s=b.decode('xutf-8')
方法
7、\b退格符;\n换行符;\r回车符;\t制表符;\''
双引号;\'
单引号;\\
反斜线
8、print("%8.3f" %value)
输出value中小数点后保留三位,最小宽度为8
print("%08.3f" %value)
输出value中小数点后保留三位,最小宽度为8,左边补0
9、字符串a.title()每个单词的首字母大写;a.lower()每个字母小写;a.upper()每个字母大写
10、
- a.startwith()是否以xxx开头
- a.endwith()查找a是否以xxx结尾
- a.find()查找xx出现的位置
- a.replace(‘it’,‘xxx’)将字符串中所有it替换成xxx
11、字符串分割、连接
a.split('.')
将字符串按照点进行分割'/'.join(list)
使用’/'作为分割符,将list连接成字符串
12、str.strip()
删除字符串前后空白;str.lstrip()删除字符串左边空白;str.rstrip()删除右边的空白
13、True和False可以参与算数运算,分别为1和0
14、==只能比较两个变量的值;is比较两个对象是否为同一个对象;id()用于判断变量所引用的对象的内存地址,如果两个内存地址不同,则通过is判断结果为False
15、"in"运算符,可以判断某个成员是否位于序列中,可以用于判断字符串是否包含特定字符串