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())# 分割字符串,返回listprint(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("""javano.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'])# 通过方法来获取,不存在返回Noneprint(map.get('key1'))# 不存在返回默认值0print(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)

is 与 ==

is 判断的时内存地址

== 会去调用类的 __eq__ 函数来进行比较

变量与赋值

a=5

值传递与引用传递

python 的引用机制同 java,本质上都是值传递,无法实现类似于 c++ 的引用传递效果

函数

函数定义

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的默认值为10def f(a=10):    print(a)
def f(x,y):    print(x)    print(y)# 这里通过指定参数名,可以颠倒参数的顺序f(y=1,x=2)
# 使用这种方式,kw能把接收到参数组合成一个mapdef 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/0except:    print('catch exception')# 捕获某个异常try:    b=a/0except ZeroDivisionError as e:    print('catch exception:',e)# 捕获多个异常try:    b=a/0except (ZeroDivisionError,IndexError) as e:    print('catch exception:',e)# 增加finally语句,finally语句无论是否发生异常都会执行try:    b=a/0except:    print('catch exception')finally:    print("finally")

python常见的内置异常

异常名含义
Exception大多数异常的基类
SyntaxError无效语法
NameError名字(变量、函数、类等)不存在
ValueError不合适的值
IndexError索引超过范围
ImportError模块不存在
IOErrorI/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.__agePerson.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):    passsuperDog = KillingMachineDog()superDog.bark()superDog.kill()

模块和包

模块的导入

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

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

包的导入

import 子包1.模块3.pyfrom 子包1.模块3 import *

__init__.py 在 python3 中不是必须的

迭代器

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

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

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

# 将容器包装成一个迭代器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的平方的mapmap = {i:i**2 for i in range(10)}

集合生成式

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

协程

import asyncioasync def web():  return requests.get('http://baidu.com').textasync def main():  print(await web())asyncio.run(main())

asyncio 的原理是维护一个 eventloop,每次遍历协程任务,当协程任务让出控制权,eventloop会继续遍历其他协程任务

future

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:  fut = executor.submit(web)  while not fut.done():    continue  print(fut.result())

函数式编程

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

函数作为参数

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+yprint(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[1],kw)        fun(*args,**kw)    return wrapperclass A:    # 加上这一行等于 m = aop(m)    @aop    def m(self, name):        print('method invoke ' + name)a = A()a.m('a')# 输出# aop拦截参数: a {}# method invokea

一些语言特性

切片

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=2ret = 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:    passexcept:    print('发生异常')else:    print('没有发生异常')

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

函数

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

metaclass

通过在创建类时指定 metaclass,可以控制类的创建过程

class Mymeta(type):    def __init__(self, name, bases, dic):        # 当 Foo 创建时,会进入到这里        super().__init__(name, bases, dic)        print('===>Mymeta.__init__')        print(self.__name__)        print(dic)        print(self.yaml_tag)    class Foo(metaclass=Mymeta):    yaml_tag = '!Foo'    def __init__(self, name):        print('Foo.__init__')        self.name = namefoo = Foo('foo')

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')

上下文管理器

Python 的 with 语句,类似于 Java 的 try(...),在离开作用域后会自动释放资源

在被创建时,首先会调用__init__ 方法,然后会调用 __enter__ 方法,由 __enter__ 方法返回需要被管理的对象,在离开作用域时,会调用 __exit__ 方法

全局解释锁

为了实现多线程下内存管理(尤其是垃圾回收机制)的线程安全,同时 Python 通过引用计数来管理对象的生命周期,但引用计数在多线程环境中容易引发竞争条件(race conditions)。GIL 可以确保引用计数的操作是原子性的,从而避免这些竞争条件

CPython大量使用C语言库,但大部分C语言库都不是线程安全的

垃圾回收

Python 将所有对象分为三代。刚刚创立的对象是第 0 代;经过一次垃圾回收后,依然存在的对象,便会依次从上一代挪到下一代。而每一代启动自动垃圾回收的阈值,则是可以单独指定的。当垃圾回收器中新增对象减去删除对象达到相应的阈值时,就会对这一代对象启动垃圾回收

为了解决引用计数在发生循环引用无法回收的问题,Python 引入了一个基于跟踪的垃圾收集器 gc.collect(),其原理是通过图搜索来发现不可达的对象

序列化

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

进程与线程

进程

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

线程

import threadingdef f():    print('sub thread')# 创建线程并启动t = threading.Thread(target=f)t.start()# 等待子线程执行完毕才继续往下执行t.join()print('main thread')
import threadingcount = 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

pbd

import pdba = 1pdb.set_trace() # 在此处暂停后可以执行一些 pbd 的脚本 比如输出变量、修改变量、跳转代码等print(a)

cProfile

使用 cProfile 可以统计代码运行的性能

import cProfile# def fib(n)# def fib_seq(n):cProfile.run('fib_seq(30)')
         7049218 function calls (96 primitive calls) in 12.151 seconds   Ordered by: standard name   ncalls  tottime  percall  cumtime  percall filename:lineno(function)        1    0.000    0.000   12.151   12.151 <string>:1(<module>)7049123/31   12.151    0.000   12.151    0.392 main.py:1(fib)     31/1    0.000    0.000   12.151   12.151 main.py:9(fib_seq)        1    0.000    0.000   12.151   12.151 {built-in method builtins.exec}       31    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}       30    0.000    0.000    0.000    0.000 {method 'extend' of 'list' objects}

python编码风格

变量和函数

「全小写+下划线」

max_capacity = 10

类名

「驼峰写法」

class CodeGenerator:    pass

异常名

「驼峰写法」

ValueError

常量

「全大写+下划线」

MAX_VALUE=100

模块名和包名

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

open_api

包名仅使用小写字母命名

requests

缩进

每级缩进应使用 4 个空格

换行

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

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

导入

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

注释

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