Python
Python
Python虽慢但功能齐全,是一门工程语言。
基础
简单语法
- pip 包管理
# 默认python的管理工具为 pip
# 更新 pip 到最新版
python -m pip install --upgrade pip
# 安装最新版
pip intsall package
# 安装指定版本
pip install package==1.0.1
# 安装最小版本
pip install package>=1.0.1
# 更新指定包,默认最新版
pip install --update package
# 卸载指定包
pip uninstall package
# 获取已经安装的包 [可升级的包]
pip list [-o]
# 获取详细信息
pip show [-f package]
数据类型
- 弱类型
- 变量都是弱类型的,使用时会动态变化。
- 基础类型 int、float、complex、str、bool、None等6种。
- 基础类型 int、float、str 的内存都是动态分配的。
- 基础类型 function,内存处理相似于其他基础类型。
# int-类型-十进制
int = 100
# int-类型-八进制
int = 0o100
# int-类型-十六进制
int = 0x100
# 浮点类型
flo = 100.02
# 复数类型
com = 1+2j
# 字符串类型
str = 'hello world'
# False/None/0/0.0 都为 false
# True/... 都为 true
bol = False
# None 即为 python 中的 null 值
null = None
# 函数类型
def demo():
print('hello world!')
# 函数也可以作为普通变量
hel = demo
# 转化为 int
a = int(x)
# 转化为 浮点数
a = float(x)
# 转化为 字符串
a = str(x)
# 转化为 char
a = chr(x)
# 将字符转化为整形
a = ord(x)
# 将整数转化为16进制
a = hex(x)
# 将整数转化为 8进制
a = oct(x)
- String
-
'str'
"str"
"""str"""
string定义。 - string 拼接,长度空格大小写,格式化,正则匹配。
- string 索引 0 ~ n。
- string len(str),需要根据场景改变编码格式。
# 'str' 标准定义,内部可转义,但内部不能有 `''`
x = 'hello world'
# "str" 常用定义,可转义,可添加 `''`
x = "I can't go!"
# """ str """ 多行定义格式
x = """
hello!
My world!
"""
# 字符串重复、拼接,* + (* 优先级大于 +)
x = 'hello' + ' ' + 'world' * 2
# 支持切片、索引,str[start:end:step]
print(x[0:],x[0],x[-1])
# 字串查询,find不存在为 -1,index不存在会报错:('str',start,end)
print(x.find('nt'),x.index('he'))
# 查询字串是否存在,查询字串出现的次数
print('hello' in x,x.count('h'))
x = "哈哈"
# 此处默认 Utf-8,可选参数 gbk或其他编码格式
y = x.encode()
# len(x) 2 len(y) 6 需要根据场景转换编码格式
print(x,y) # \xe5\x93\x88\xe5\x93\x88 哈哈
# string 转换大小写
print(x.lower(),x.upper())
# 去除string两侧、左侧、右侧指定字符串,一般都是特殊字符
print(x.strip('st'),x.lstrip('l'),s.rstrip('r'))
# index索引,格式化字符串
x = "name {} age {}"
print(x.format('zsh',22)) # name zsh age 22
# hash映射,格式化字符串,支持多点映射
x = "name {name} {name} age {age}"
print(x.format(name="zsh",age=22)) # name zsh zsh age 22
x = "hello world"
# 默认 空格,将原string分割为 list
y = x.split()
# 以指定 'str' 将原string分割为 list
y = x.split('o')
x = ['www','baidu','com']
# 将指定 list 以指定分隔符 '.' 连接为 string
print('.'.join(x)) # 'www.baidu.com'
print(''.join(x)) # 'wwwbaiducom'
# 正则匹配模式 ^start [dat]{freq}(time) end$
# re 模块,正则会用到
- 函数
- function 定义与内存处理同等与基础类型。
- function 内限定局部变量,外部为全局变量。
- function 支持右侧参数设定默认值。
- function 支持 lambda 语法糖定义函数。
- function
*
**
系参数都是动态深拷贝。 - function
*
将连续的参数转为tuple
。 - function
**
将连续的参数映射,转化为字典类型。
# python function 基础定义
def demo():
print('hello world')
exp = demo
# 完全相似于基础变量的内存管理
print(id(exp),id(demo))
demo()
exp()
x = 100
# 函数内部为局部变量区域
def demo():
# 此时输出函数外变量
print(x)
# 存在默认值的参数必须在右边,否则会报错
def demo(dat,tmp='hello')
print(dat+tmp)
# 语法糖生成简单函数
# 参数列表:自动返回表达式
demo = lambda a : a*a
# 参数列表:自动执行语句块
demo = lambda a : print(a*10)
# 将原始参数转化为一个元组
def demo(*dat):
for val in dat:
print(val)
# 将原始参数转化为字典
def test(**dat):
for key,val in dat.items():
print(key+':'+str(val))
# 动态传参,参数执行深拷贝
demo(1,2,3)
test(a=1,b=2,c=3)
# 匿名函数回调
def demo(args, fun):
print("function demo running")
fun(args)
demo("hello world",lambda args:print(args))
# 闭包函数,注意内存泄漏
def demo(args):
return lambda : print(args)
demo("hello world")()
语法控制
- 运算符
# 加 减 乘 除
+ - * /
# 整除 求余 求幂
// % **
# 赋值运算
= += -= *= /= //= %= **=
# 比较运算
> >= < <= == !=
# 逻辑运算
and or not
# 与 或 反 异或 左移 右移
& | ~ ^ >> <<
- 流程控制
# if
if True:
pass
# if else
if True:
pass
else:
pass
# if elseif else
if True:
pass
elif True:
pass
else:
pass
# while 循环
while True:
pass
# for 循环
for i in range(1,10,2):
print(i)
# break continue
- 异常处理
异常类型 | 异常说明 |
---|---|
NameError | 访问一个不存在的变量 |
IOError | IO 异常 |
MemoryError | 内存溢出或不足 |
ValueError | 传入值错误 |
IndexError | 索引出界异常 |
ImportError | import 导包异常 |
TypeError | 类型异常 |
… | … |
- assert 1 == 0 判断是否中断程序。
- try except finally 标准的异常处理块。
- raise ExpError(“ExpMsg”) 主动抛异常,一般配合if使用。
# raise 用于主动抛出异常
def det(dat):
if dat == 10:
raise IndexError("demo-10")
return 100/dat
# try except finally 处理异常
try:
print(det(0))
# 手动抛出异常,一般配合 if 使用
raise IndexError("demo")
# 捕获系统抛出的异常
except ZeroDivisionError as err:
# err 异常信息
# err.with_traceback() 获取异常栈信息
print(err)
# 捕获自己抛出的异常
except IndexError as er:
print(er)
finally:
print("end")
# 调试专用,根据条件中断进程
# True 则继续执行 Flase 会中断进程,并输出异常信息
assert 1 == 0
数据结构
- 归纳分析
- python struct 都是容器类型,只存引用,内存动态化。
- python struct 内部依然是弱类型的,可组成灵活的嵌套结构。
- python list/tuple set 可组成灵活的数据结构体。
- python dict 相似于 lua-table/Json 等数据操作方式。
# list tuple set 这三种容器是可以相互转化的
x = [1,2,3,4]
y = tuple(x)
z = set(x)
# dict key 可由 tuple/obj组成,value则无限制
d = { y:x }
# list tuple set dict 容器特性,引用连接导致内部无限定
x = [1,2,'3']
x = (1,2,'3')
x = {1,2,'2'}
x = {1:1,'1':'2'}
# list tuple set dict 都可以使用推导式创建
# list = [ exp for if ]
# tuple = ( exp for if )
# set = { exp for if }
# sict = { exp1:exp2 for if }
# len str (a in b) 等方法皆适用 list tuple set dict
print(len(x),str(x),a in b)
# list tuple set dict 浅拷贝
new = old
# list set dict 深拷贝
# tuple 是不可变的,一个副本就够了,所以没有 copy 方法
new = old.copy()
# list set dict 内存都是动态管理
dat.clear()
序列
- 基本结构
- python list 可以当做数组、链表。
- python list 可执行动态切片功能。
- python list 亦可执行
+
*
。
x = [1,2,3,'4']
# list 正数为 0~n,负数则是反向序数索引
print(x[0],x[-1])
# 切片功能 x[start:end:step]
# 半开区间 [start,end) step 可省略,默认为 1
print(x[1:2:1])
# 可重复链接 list
print(x*2,x+x)
# range 类,内部为迭代函数
x = range(1,10)
# 此处将迭代函数实现为 list
x = list(x)
# enumrate,index-value 组,内部为迭代函数
x = enumerate(x)
# (0,1) (1,2) (2,3) ...
# 遍历 value,非循环内部变量
for value in y:
print(value)
# 遍历 index value,非循环内部变量
for index,value in enumerate(y):
print(index,value)
- 增删改查 sort
x = [1,2,3,4]
# insert
# append 无返回值
# append 在末端链接一个数据结构
x.append(5) # [1,2,3,4,5]
x.append(x) # [1,2,3,4,[1,2,3,4]]
# extend 无返回值
# extend 在末端链接一个数据结构中的所有数据
# x+y 系列的方法,默认就是用这个方法
x.extend(x) # [1,2,3,4,1,2,3,4]
# insert 无返回值
# insert(index,val),index 支持正负
# index 之前插入,val 值
x.insert(0,0)
# delete
# pop 返回 val,并删除此 val
# x.pop()命中最后一个 val
# x.pop(index) 用索引命中 val
x.pop() # 4
x.pop(0) # 1
# remove 无返回值
# 删除指定 val
x.remove(1)
# remove 一般配合 if 使用
if 1 in x:
x.remove(1)
# update
# 更改操作一般直接用 索引、切片
x[0] = -1
x[0:2] = [-1,-2]
# select
# 判断 val 是否在 list 中
print(1 in x)
# 计数 list 存在多少个 val
print(x.count(1))
# 返回命中的第一个索引
print(x.index(1))
# 此处带区间
print(x.index(1,0,2))
# sort 无返回值,排序方式,排序方向等都可设置
x.sort()
# 反排序
import random
# 将原 list 顺序打乱重排
random.shuffle(x)
元组
- 基本结构
- python tuple tuple 就是不可变的 list。
- python tuple 处理速度较快与list,选择合适的场景即可。
# 元组与list相似,内部节点相互独立
x = (1,2,3,'4')
# 元组可做 * 运算
print(x*2)
# sum len str max min 等常用函数亦支持
x = tuple(range(1,10))
# count index 及标准索引等方法亦支持
print(x.count(1),x.index(1),x[0])
# x[start:end:step] 亦支持切片
print(x[2:],x[:2],x[1:4:2])
x = (1,2,3,4)
# tuple 支持 + 运算,但必须为同类型
print(x+x)
# tuple 没有 append extend insert remove pop 等方法
# tuple 只要被创建,既无法被修改,只能删除或被清理
集合
- 基本结构
- python set 本质是一个无序不重复的集合。
- 集合本身都是可以做交并补等集合运算的。
# 集合本身会将重复对象自动过滤
x = {1,2,'2',2} # {1,2,'2'}
# 添加、删除 对象
x.add(3)
x.remove(3)
# 扩展的添加删除对象
x.update(1,2,3) # 一次性添加多个元素
x.discard(1) # 安全移除集合元素(可能不存在)
# 集合本身无序,只能随机 pop 出一个对象
x.pop()
# 交并补等运算 ......
# 迭代集合
for i in x:
print(i)
字典
- 基本结构
- python dict key:value 映射关系。
- python dict key 是不可变的,value无限制。
# 标准定义方法
x = { "a":1, "b":2 }
# key 唯一且不可变,类型无限制,不能是标识符a、b等,value 无限制
x = { 1:1, 2:"a" }
y = [1,2,3]
z = (1,2,3)
# 快捷创建字典,z必须为tuple
x = {z:y}
# zip(a,b) 将多个 list/tuple 转化为元组组成的zip对象
# dict(a,b) 则是将元组、列表或元组 组成字典对象
x = dict(zip(z,y))
# 此处设计友好,但实际 标识符被转化为 string
x = dict(a=1,b=2)
# 实际创建字典 {1:None,2:None}
x = dict.fromkeys([1,2])
x = {"a":1,"b":2}
# 判断是否存在此 key
if "a" in x:
print(x["a"])
# 获取 key --> value,和 lua 蛮像的
print(x["a"],x.get("a"))
# 新增或修改都可以以来这个操作
x["c"] = 3
# 此时迭代每一组,且转化为 元组 (key,value)
for item in x.items():
print(item)
设计
面向对象
基础部分
- 组成部分
组成 | 说明 | 初始化 | 访问 |
---|---|---|---|
类变量 | 非构造函数内定义的类内变量 | 加载模块 | 类/对象 |
类函数 | 参数没有self 的任意类内函数 |
加载模块 | 类/对象 |
成员变量 | 构造函数内定义的变量 | 初始化对象 | 对象 |
成员函数 | 参数携带self 的任意类内函数 |
初始化对象 | 对象 |
默认 | 所有类都附带的方法和变量 | 加载模块 | ~ |
- 访问控制权限
适用于所有类的组成部分。
类型 | _ |
__ |
|
---|---|---|---|
示例 | exp | _exp | __exp |
访问区域 | 无限制 | 本模块、子类 | 类内部 |
对比-Java | public | protected | private |
class exp:
# 类变量,exp.msg obj.msg 即可访问
msg = 'static-value'
# 类方法,exp.show() obj.msg 即可访问
def show():
print('static-function')
# 构造方法
def __init__(self,x,y=10):
# 无任何前缀的变量,可随意访问,public
self.x = x
# _ 前缀的变量,子类、本类、本模块可访问,protected
self._y = y
# __前缀的变量,仅能内部访问,private
self.__z = z
# function 存在self,则为对象方法,否则为类方法
def show(self):
print(self.x,self.y)
def _sh0(self,z):
print(self.x,self.y,z)
def __sh(self,z):
print(self.x,self.y,z)
# 被 property注解的方法,参数只有self,且存在返回值
# 对象调用此对象方法时,可以直接当做变量来用
@property
def exec(self):
return self.__z
# 新建对象
obj = exp(10)
# 类级别变量,都可引用
print(exp.msg,obj.msg)
# 对象方法,注意权限控制
exp.show()
# 被 property 注解的方法,
print(exp.exec)
抽象化
面向对象本质就是代码设计抽象化的过程。
- 类基础方法
-
__init__
构造方法 -
__del__
析构方法 -
__str__
string化对象 -
__cmp__
比较 obj
这些方法都可以被重写,构造方法一般需要重写。
- 继承
子类
super()
获取父类引用,self
获取自身引用。
# 父类 demo
class demo:
def __init__(self,x):
self.__x = x
@property
def get_x(self):
return self.__x
# 子类 exp 继承 demo
class exp(demo):
def __init__(self,x,y):
# super() 即为父类引用
super().__init__(x)
self.__y = y
def get_y(self):
return self.__y
ex = exp(10,12)
# 同时访问父类与子类的方法
print(ex.get_x,ex.get_y())
- 重写
自定义实现的 init 就是重写此方法。
# __init__ 可自动初始化
class fat:
def show(self):
print('father')
def sh(self):
print('ok')
# 继承过程中,__init__ 亦可自动初始化
class son(fat):
# 子类重写父类方法
def show(self):
print('son')
# 调用重写的方法
son().show()
# 掉用父类方法
son().sh()
- others
- python 没有抽象类与接口,需引入abc包(不推荐)。
- python 过程式为主,简单快速,没必要非要搞得很复杂。
# getter setter
class demo:
def __init__(self,x):
self.x = __x
# @property 注解,无参数,存在返回值才可注解
def get_x(self):
return self.__x
def set_x(self,x)
self.__x = x
模块化
- 模块
- python 导入模块类似于Lua。
- 先在
sys.modules
中查找模块是否已加载。 - 若模块已加载则直接返回索引。
- 若未加载则先加载至
sys.modules
中,再返回索引。 - 默认模块名就是索引,可
as
自定义。 - 模块之间可限定访问权限与附加操作。
sys.path
默认加载路径。sys.modules
已完成加载的模块。
# 导入包,as 用于重命名
import sys as sys
# 导入模块中的某一个引用,可以是对象,亦可以是函数
from sys import path
# 遍历输出所有,模块加载路径
for v in sys.path:
print(v)
# 遍历输出,所有已被加载的模块
for v in sys.modules:
print(v)
# 热更新思想,就是删除已加载的模块,继续加载一次
import exp
# 热更新基础原理,类似于 lua
if 'exp' in sys.modules:
del sys.modules['exp']
import exp
# python3 之后自带的,热更新方法
from imp import reload
reload(exp)
# exp 模块
def demo():
# 此处可限定其他模块引用的附加操作
if __name__ == '__main__':
print("self using")
else:
print("others using")
# test 模块
import exp
exp.demo() # others using
- 包
- python 包就是一个自带
__init__.py
的文件夹。 - python 包本身是个 namespace,内部控制其他模块。
-
__init__.py
的__all__
可设定 * 匹配值。 -
__init__py
在import 时执行,一般空即可。
exp
__init__.py
demo.py
# package.module_name
import exp.demo as demo
# __init__.py
__all__ = [ "module_1","module_2" ]
# 此时仅会导入 __all__ 链表中的模块
import exp.*
内存管理
- 弱类型 容器
- python 的所有对象都是弱类型的。
- 语言中,弱类型对象执行时才可确定对象类型。
- 即弱类型语言仅在执行时变量才会申请内存。
- 容器类对象,仅提供指向具体内存的引用(指针),不提供具体空间。
- 引用计数器
- python 普通对象的申请与Java-常量池非常相似。
- 引用计数器,即指程序会记录内存块被引用的数量。
- 某个对象的引用计数器为 0~n 之间,为零即会被回收。
- GC 分代
- python GC,停止所有运行线程。
- python GC,和对象无关,只和内存块以及引用计数器相关。
- python GC,自动触发执行,new – free > sta(700) 即执行。
- python 内存块分代,new -> 0代,之后逐次变化。
- 内存分级
- python 内存总体是一个金字塔类型。
- -1 -2 层,这部分 OS 控制,与python无关。
- 0 层,某些内存需求大于256k,python利用malloc,free控制堆内存。
- 1 2 层,这部分即为内存池,python控制存一些小内存的变量。
- 3 层,这一层由程序员完全控制即可。
# x 被使用时,才会解析变量类型,以确定内存大小,0 代
x = 100
# y、x 同时指向一块内存,引用计数器为 2
y = x
# 执行常量池原则 ,x、y、z 指向一块内存,引用计数器为 3
z = 100
# 清除 z 的引用相关,原始内存的引用计数器为 2,x、y依然正常使用
del z
# 容器类对象,内部只存对象引用
dat = [1,2,3]
# 改变 dat[0]所指向的内存块的引用计数为0,然后再删除dat[0]节点
del dat[0]
# 改变 dat 对象或递归对象所指向的内存块的引用计数为 0
del dat
pass
# 执行GC,除主线程-执行GC,其他线程全部停止
# 引用计数为 0 的清除,继续存活的逐渐升级迭代
adr = id(x) # int 提供对象的实际内存地址
ok = x is y # bool 判断两个对象是否指向一个内存地址,内部id()
del(x) # None 将实际内存地址的引用计数:减一,并清除此对象
常用
方法
- 包括 时间、文件、网络IO、系统等的一些处理。
- 通用
# 1 ~ 10,间隔 2
x = range(1,10,2)
# 四舍五入
x = round(10.2,2)
# 求和
x = sum(range(1,10))
# 10 的4次幂
x = pow(10,4)
# 时间模块
import time
# 程序休眠 10 秒
time.sleep(10)
# 时间戳
print(time.time())
# 时间 2020-02-29 00:00:12
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
# 打开二进制文件
file = open('exp.png','rb')
file.close()
# 安全操作文件,避免中途出现异常,导致文件被锁或损坏
with open('exp.txt','w') as file:
file.read()
file.write("...")
file.close()
pass
模块
- 一些主要的模块,sys、os、time。