Python

数据类型

数据结构

列表

# 列表中的元素可以是任意类型的
list = [1,'2',3.0]
# 通过下标来获取/修改元素
list[0]='a'
print(list[0])
# 通过len函数来获取列表长度
print(len(list))
# 通过list的append函数来添加元素
list.append('xx')
# 查看元素在列表中的下标
print(list.index(3.0))
# 查看元素是否在列表中
print('2' in list)
# 统计列表中某元素的数量
print(list.count(1))
# 向某位置插入元素,如果提供的下标超出列表的大小,会插在最后
list.insert(0,'x')
# 添加一个列表
list.extend([5,5,5])
# 根据下标删除元素并返回
x = list.pop(0)
# 直接删除指定下标位置的元素
del list[0]
# 删除并返回最后一个元素
x = list.pop()
# 直接删除元素
list.remove('2')
# 反转列表
list.reverse()
# 排序
list.sort()
# 清空列表
list.clear()

元组

元组创建完成后,便不能向其中添加元素,也不能修改和删除其中的任何一个元素

# 空元祖
items = ()
# 一个元素的元组,需要在最后加一个(,),如果括号中只有一个元素,那么 Python 会将这个括号当作优先级符号进行处理
items=(1,)
# 多个元素的元组
items=(1,2,3)
# 获取元素
print(items[2])
# 获取下标
print(items.index(2))
# 是否存在
print(2 in items)
# 统计元素个数
print(items.count(1))

字符串

字符串是字符的有序序列,所以也具有索引。也可以根据索引取出其中某一个字符

print('cxk'[2])
# 字符串是不可变的,所以不能通过下标修改
# 'cxk'[2]='b'
# 同样可以用len获取长度
print(len('cxk'))
str = 'java language'
# 查找子串
print(str.find('ang'))
# 判断子串
print('ava' in str)
# 统计子串数
print(str.count('a'))
# 是否以某子串开头
print(str.startswith('ja'))
# 是否以某子串结尾
print(str.endswith('ge'))
# 字符串替换
print(str.replace('java','python'))
# 去除字符串前后空白字符
print(str.strip())
# 分割字符串,返回list
print(str.split(' '))
# 拼接字符串
print(str.join(['so','good']))
# 转成大写形式
print(str.upper())
# 转成小写形式
print(str.lower())
常用的转义字符 含义
\' 单引号
\" 双引号
\\ 反斜杠
\n 换行符
\t 制表符(Tab)
\r 回车
# 原始字符串,有啥就是啥
print(r'java \t no.1')
# 多行字符串,输出的字符串不换行
print('java no.1\
    yes!\
    ')
# 输出的字符串换行
print("""
java
no.1
""")

列表、元组、字符串的通用操作

# 长度
print(len(str))
# 获取子序列
print(str[1:10])
# 拼接子序列
print(str + '?')
# 重复序列中的元素
print(str*3)

字典

也就是map,显著优势是可以通过键快速地查询数据

# 创建空字典
map = {}
# 创建有内容的字典
map = {'key1': 1, 'key2': 2}
# 增加键值对/修改键所对应的值
map['key3'] = 3
# 通过键获取值,若键不存在则将抛出 KeyError 异常
print(map['key2'])
# 通过方法来获取,不存在返回None
print(map.get('key1'))
# 不存在返回默认值0
print(map.get('keyx', 0))
# 是否包含某个键
print('x' in map)
# 获取所有键,返回迭代器
print(map.keys())
# 获取所有值,返回迭代器
print(map.values())
# 获取键值对迭代器,每一对都是元组
print(map.items())
# 根据键删除,返回值,如果键不存在,则会抛出 KeyError 异常
map.pop('key1')
# 键不存在返回默认值,不会抛异常
map.pop('key1', 'x')
# 键不存在会抛异常
del map['key2']
# 随机弹出一个键值对
print(map.popitem())
# 用字典更新字典
map = {'key1': 'x'}
map.update({'key1': 1})

集合

其中的元素没有顺序关系。集合中的元素没有重复,重复的元素将被自动剔除最终只留下一个,集合也是用花括号({})来表示,不同于字典的是,花括号中放的是一个个数据,而不是键值对

# 创建空集合
s = set()
# 创建集合
s = {1, 2, 3, 4, 5}
# 添加元素
s.add(0)
# 并集
s.update({7, 8, 9})
# 查看元素是否在集合中
print(0 in s)
# 弹出一个元素
print(s.pop())
# 删除指定元素,如果要删除的元素不存在,则抛出 KeyError 异常
s.remove(1)
# 删除,但不抛出异常
s.discard(1)
# 求交集
print({1, 2, 3}.intersection({3, 4, 5}))
print({1, 2, 3} & {3, 4, 5})
# 求并集
print({1, 2, 3}.union({3, 4, 5}))
print({1, 2, 3} | {3, 4, 5})
# 求差集
print({1, 2, 3}.difference({3, 4, 5}))
print({1, 2, 3} - {3, 4, 5})
# 是否为子集
print({1, 2}.issubset({1, 2, 3}))
# 是否为超集
print({1, 2, 3}.issuperset({1, 2}))
# 清空集合
s.clear()

数值运算

# 加法
print(33+725)
# 减法
print(33-11)
# 乘法
print(33*25)
# 除法
print(33/22)
# 取余
print(33 % 11)
# 次方
print(33**2)
# 整除
print(33//22)

比较运算

print(2>3)
print(2==3)
print(2<=3)
print(2!=3)

变量与赋值

a=5

函数

函数定义

def sum(a,b):
    return a+b

副作用

函数包含一些会引起程序或系统状态变化的操作,如修改全局变量、命令行输入输出、读写文件等,这样的变化叫做函数的副作用

几个内置函数

# 获取终端的一个输入
str = input('input str')
# 将str转为int类型
a = int(str)
# 输出
print(a)

python内置函数

内置函数 功能 示例 示例结果
dict() 将参数转换为字典类型 dict(a=1, b=2, c=3) {'a': 1, 'b': 2, 'c': 3}
float() 将字符串或数字转换为浮点型 float('0.22') 0.22
int() 将字符串或数字转换为整数型 int(1.23) 1
list() 将元组、字符串等可迭代对象转换为列表 list('abc') ['a', 'b', 'c']
tuple() 将列表、字符串等可迭代对象转换为元组 tuple([1, 2, 3]) (1, 2, 3)
set() 1.创建空集合;2.将可迭代对象转换为列表集合 set('abc') {'b', 'a', 'c'}
str() 将参数转换为字符串 str(3.14) '3.14'
bytes() 将参数转换为字节序列 bytes(4) b'\x00\x00\x00\x00
内置函数 功能 示例 示例结果
max() 求最大值 max([13, 2, 0.6, -51, 7]) 13
min() 求最小值 min([13, 2, 0.6, -51, 7]) -51
sum() 求和 sum([13, 2, 0.6, -51, 7]) -28.4
abs() 求绝对值 abs(-51) 51
pow() 求次方 pow(2, 10) 1024
bin() 转换为二进制 bin(77) '0b1001101' (注意结果为字符串)
hex() 转换为十六进制 hex(77) '0x4d' (注意结果为字符串)
round() 浮点数四舍五入 round(4.5678, 2) (第二个参数为小数精度) 4.57
内置函数 功能
bool() 判断参数是否为真,为真则返回 True,否则返回 False。「为真」指的是,表达式的结果为布尔值 True,或非零数字,或非空字符串,或非空列表
all() 如果可迭代对象中的所有值,在逐一应用 bool(值) 后结果都为 True,则返回 True,否则返回 False
any() 如果可迭代对象中的任意一个或多个值,在应用 bool(值) 后结果为 True,则返回 True,否则返回 False
内置函数 功能
input() 从标准输入中读取字符串
print() 将内容写入标准输出中
open() 打开一个文件。之后便可以对文件做读写操作
内置函数 功能
type() 获取对象的类型
isinstance() 判断对象是否是某个类(或其子类)的对象
dir() 获取类或对象中的所有方法和属性;无参数时获取当前作用域下的所有名字
id() 返回一个对象的唯一标识。在我们所使用的 CPython 中这个唯一标识实际为该对象在内存中的地址
# 得到有关int函数的相关信息
help(int)
# 排序
print(sorted([3,5,7,1]))
# 获取一个整数序列
print(range(100))

函数进阶

# 如果省略a,则a的默认值为10
def f(a=10):
    print(a)
def f(x,y):
    print(x)
    print(y)
# 这里通过指定参数名,可以颠倒参数的顺序
f(y=1,x=2)
# 使用这种方式,kw能把接收到参数组合成一个map
def f(**kw):
    print(kw)
    
f(x=1,y=2,z=3)
# 类似于java的可变参数
def f(*kw):
    print(kw)
    
f(1,2,3)
def f():
    x=1
    y=2
    return x,y
    
a,b=f()

逻辑关键字

分支语句

需要注意的是,python使用的缩进来代表c/java中的花括号

if a<18:
    print('未成年')
elif a>=18 and a<=20:
    print('还年轻')
else:
    print('成年')

循环语句

while a>=0:
    print(a)
    a = a-1
list = [1,2,3]
for i in list:
    print(i)

错误处理与异常机制

异常捕获

# 捕获所有异常
try:
    b=a/0
except:
    print('catch exception')
# 捕获某个异常
try:
    b=a/0
except ZeroDivisionError as e:
    print('catch exception:',e)
# 捕获多个异常
try:
    b=a/0
except (ZeroDivisionError,IndexError) as e:
    print('catch exception:',e)
# 增加finally语句,finally语句无论是否发生异常都会执行
try:
    b=a/0
except:
    print('catch exception')
finally:
    print("finally")

python常见的内置异常

异常名 含义
Exception 大多数异常的基类
SyntaxError 无效语法
NameError 名字(变量、函数、类等)不存在
ValueError 不合适的值
IndexError 索引超过范围
ImportError 模块不存在
IOError I/O 相关错误
TypeError 不合适的类型
AttributeError 属性不存在
KeyError 字典的键值不存在
ZeroDivisionError 除法中被除数为 0

抛出异常

try:
    raise ValueError("参数错误")
except ValueError as e:
    print('catch exception:',e)

面向对象

查看数据类型

print(type(''))

类的定义

class Person:
    pass # pass是占位符

实例化

p = Person()

属性

class Person:
    # 增加构造器参数,self,定义时必须有这个参数,但是调用时不必传递,等同于this
    def __init__(self,firstName,lastName):
        self.firstName = firstName
        self.lastName = lastName
# 创建对象时传入参数
p = Person('c','xk')
# 访问属性
print(p.firstName)

方法

class Person:
    # 省略...
    def say(self):
        print(self.firstName+self.lastName)
# 调用方法
p.say()

进阶

class Person:
    # 定义一个类变量
    people = '70亿'
    # 定义一个类方法
    @classmethod
    def go(klass):
        print(str(klass)+'go')
# 使用
print(Person.people)
Person.go()
class Person:
    ...
    # 定义一个静态方法,区别在于不用传入klass
    @staticmethod
    def go0():
        print('static go')
class Person:
    # 定义一个类私有属性
    __people = '70'
    @classmethod
    def f(klass):
        print(Person.__people)
    def f1(self):
        # 私有成员变量
        self.__age=15
        return self.__age

Person.f()
p = Person()
print(p.f1())
# 会抛异常
p.__age
# 会抛出异常
print(Person._people)

头尾有双下划线的方法都是特殊方法

__init__()用于对象的初始化。在实例化类的过程中,被自动调用,就是构造器

__next__() 对迭代器调用 next() 函数,便能生成下一个值。这个过程的背后,next() 调用了迭代器的 __next__() 方法

__len__() 实现了 __len__() 方法,调用 len() 函数时将自动调用容器的__len__()方法

__str__() 在使用 print() 函数时将自动调用类的 __str__() 方法,toString()

__getitem__() 'abc'[2] 即等同于 'abc'.__getitem__(2)

class Animal:
    def run(self):
        print('animal run')

class Dog(Animal):
    def __init__(self):
        # 调用父类的构造器
        super().__init__()
    # 覆写父类的方法
    def run(self):
        print('dog run')
    def bark(self):
        print('wolf wolf')
dog = Dog()
dog.run()
dog.bark()
class MachineDog:
    def kill(self):
        print('machine dog kill you')
class Dog(Animal):
   ...
class KillingMachineDog(Dog,MachineDog):
    pass
superDog = KillingMachineDog()
superDog.bark()
superDog.kill()

模块和包

模块的导入

# 导入模块
import random
# 使用模块
print(random.randint(1,9))

包/
├── __init__.py
├── 模块1.py
├── 模块2.py
├── 子包1/
    ├── __init__.py
    ├── 模块3.py
    └── 模块4.py
└── 子包2/
    ├── __init__.py
    ├── 模块5.py
    └── 孙子包1/
        ├── __init__.py
        └── 模块6.py

包的导入

import package.subpackage.module

迭代器

迭代指的是通过重复执行某个操作,不断获取被迭代对象中的数据。这样的每一次操作就是就是一次 迭代

迭代器可以提供迭代功能,当我们需要逐一获取数据集合中的数据时,使用迭代器可以达成这个目的

迭代器可以不保存数据,它的数据可以在需要时被计算出来(这一特性也叫做惰性计算)

# 将容器包装成一个迭代器
iterator = iter([1,2,3,4])
# 不断迭代,直至迭代完抛出异常
while True:
    print(next(iterator))

python的for循环迭代就是通过使用迭代器完成的

可迭代

定义了 __iter__() 方法的类对象就是可迭代的。当这个类对象被 iter() 函数使用时,将返回一个迭代器对象

自定义迭代器

class MyIterator:
    # 定义了这个方法就代表是可迭代的
    def __iter__(self):
        self.count=0
        return self
    # 实现可迭代对象的接口
    def __next__(self):
        self.count = self.count+1
        return self.count
# 使用
i = MyIterator()
for i in i:
    print(i)

生成器

yield 语句的作用和 return 语句有几分相似,都可以将结果返回。不同在于,生成器函数执行至 yield 语句,返回结果的同时记录下函数内的状态,下次执行这个生成器函数,将从上次退出的位置(yield 的下一句代码)继续执行

# 另外一种定义迭代器的方式
def f():
    for i in range(10):
        yield i

# 使用
i = f()
for j in i:
    print(j)

生成器表达式

生成器 = (针对项的操作 for 项 in 可迭代对象)
# 输出0-9每个数的平方
for i in (j**2 for j in range(10)):
    print(i)

也可以加上if语句

# 输出0-100中偶数的平方
for i in (j**2 for j in range(100) if j%2==0):
    print(i)

字典生成式

{键: 值 for 项 in 可迭代对象}
# 生成0-10的键为i,值为i的平方的map
map = {i:i**2 for i in range(10)}

集合生成式

# 生成0-10的集合
set = {i for i in range(10)}

函数式编程

def say():
    print('say')
# 函数可赋值给变量并调用
f = say
f()

函数作为参数

def f(callback):
    callback('date')
def f1(x):
    print(x)

f(f1)

lambda表达式

# 上面的函数调用也可以缩写成
f(lambda x: print(x))

函数作为返回值

def f():
    return lambda x,y: x+y

print(f()(1,2))

map与filter

# filter函数可对一个可迭代对象做过滤,符合过滤lambda的元素会被返回
l = filter(lambda x: x%2==0,[1,2,3,4,5])
print(list(l))
l = [1,2,3,4,5]
# map函数则是对可迭代对象中的每个元素做处理,然后返回
ret = map(lambda x: x**2,l)
print(list(ret))

装饰器

自定义装饰器

def aop(fun):
    # 对fun进行包装,在其外层拦截参数
    def wrapper(*args,**kw):
        print("aop拦截参数:",args,kw)
        fun(*args,**kw)
    return wrapper

class A:
    # 加上这一行等于 m = aop(m)
    @aop
    def m(self):
        print('method invoke')

a = A()
a.m()

一些语言特性

切片

l = [1,2,3,4,5]
# 负数代表倒数第几个
print(l[-2])
# 起始索引跟结束索引默认不写就代表是第一个/最后一个
print(l[:])
# 代表从0到最后一个,步长为2取一个元素
print(l[0:-1:2])

赋值

# 连续赋值
a = b = c = 1
# 拆包
x, y = 1, 2
# 拆包一次接收多个元素
x, *y = 1, 2, 3, 4
# 交换两个元素
x, y = y, x
# or的使用
print('' or '1') # 结果为'1' 类似于js

控制语句

# 三元表达式
# 如果1=1,ret=1 否则ret=2
ret = 1 if 1==1 else 2
# for...else
# 如果可迭代对象全部都被迭代了,就会执行else语句,否则不执行else语句,while...else同理
for i in range(5):
    print(i)
else:
    print('all used')
# try except else,没有发生异常时,else语句会被调用
try:
    pass
except:
    print('发生异常')
else:
    print('没有发生异常')

# 自定义异常
class BussinessException(Exception):
    pass

函数

#     参数类型标注   返回值类型标注
def f(name:str) -> str:
    return 'hello'

IO

打开文件

f = open('test.py','r')
# 指定编码
f = open('test.py','r',encoding='gbk')

读写模式

'r':只读,若文件不存在则抛出 FileNotFoundError 异常 'rb': 以二进制的形式 'w':只写,将覆盖所有原有内容,若文件不存在则创建文件 'a':只写,以追加的形式写入内容,若文件不存在则创建文件 'r+':可读可写,若文件不存在则抛出 FileNotFoundError 异常 'w+':可读可写,若文件不存在则创建文件 'a+':可读可写,写入时使用追加模式,若文件不存在则创建文件

文件写入

f = open('a.txt','w')
f.write('a dog')

文件读取

f = open('test.py','r',encoding='utf8')
# 读出全部内容
print(f.read())
# 读出文件行的列表
print(f.readlines())

文件关闭

f.close()

文件系统操作

import os
# 创建目录
os.mkdir('./test')
# 枚举目录下的文件
for i in os.listdir('./'):
    print(i)
# 删除目录
os.rmdir('./test')
# 删除文件
os.remove('a.txt')
# 重命名文件
os.rename('test.py','test1.py')

序列化

import pickle

# 序列化成二进制
ret = pickle.dumps([1,2,3])
print(ret)
# 反序列化
print(pickle.loads(ret))
import json
# 序列化成json
str = json.dumps({'a':1,'b':2})
print(str)
# 反序列化
print(json.loads(str))

进程与线程

进程

import multiprocessing
import os
def f():
    print('子进程')
    print('pid',os.getpid())
    print('ppid',os.getppid())

# 只有主进程才创建子进程
if __name__ == '__main__':
    # 创建一个子进程
    p = multiprocessing.Process(target=f)
    p.start()
    # 等待子线程运行完毕才会继续往下走
    p.join()

线程

import threading

def f():
    print('sub thread')

# 创建线程并启动
t = threading.Thread(target=f)
t.start()
# 等待子线程执行完毕才继续往下执行
t.join()
print('main thread')
import threading
count = 0
# 创建一个锁
lock = threading.Lock()
def add():
    for i in range(2000000):
        global count
        # 获取锁
        lock.acquire()
        count = count+1
        # 释放锁
        lock.release()
    print('执行完成:当前结果:',count)
for i in range(10):
    threading.Thread(target=add).start()

安装第三方包

pip install requests --user

python编码风格

变量和函数

「全小写+下划线」

max_capacity = 10

类名

「驼峰写法」

class CodeGenerator:
    pass

异常名

「驼峰写法」

ValueError

常量

「全大写+下划线」

MAX_VALUE=100

模块名和包名

模块可使用「小写 + 下划线」

open_api

包名仅使用小写字母命名

requests

缩进

每级缩进应使用 4 个空格

换行

每行代码的最大字符数为 79。若某一行代码过长,可以将其换行书写

定义函数和类时,多个函数或类之间使用两个空行进行分隔

导入

import 按下列类型和顺序使用:

注释

注释以 # 及一个空格开始 行内注释和代码间至少要有两个空格分隔