Python


基础

基本概念

特点

  • 简单优雅,使用难度曲线平缓,可以快速上手;
  • 跨平台,在不同平台上开发;
  • 大量库(内置或第三方库)、开发快;
  • 扩展性强,可以将C/C++等高效语言包含成Python的库;
  • 解释型、动态型语言、慢;
  • 不可加密;

官方&发行

  • 官方版:只包含解释器;
  • anaconda:包含解释器及常用库包(如科学计算相关包);

工具

  • iPython:交互式解释器、代码补全等;
  • jupyter notebook/lab:通过web交互的编程环境,简洁、插件多、功能强大;
  • VScode:文本编辑器,有丰富的插件扩展;
  • pycharm:集成开发环境;
  • pip:帮助解决依赖问题;

随机函数

  • 随机数种子的作用是设置一个起点,起点的设置一次有效,但实际效果是持续的;
  • Pytorch需要专门为GPU设置seed;

书写规范

起始

#!/usr/bin/env python3 
# -*- coding: utf-8 -*-
  • 前者在Linux、Mac OS中指定编译器;后者告诉编译器用utf-8来读取源码。

库写法

if __name__ = '__main__': 
    # 当直接执行代码时,条件为True,执行;而当作为库被导入时条件为False
    pass

缩进

  • 不同级别的代码块通过缩进进行区分;
  • 缩进是4个空格,许多文本编辑器会默认将tab键转为4个空格;

注释

  • 合适比例的注释可以增强代码的可读性;
    # 注释放在这里面

命名

  • 字母下划线开头,字母下划线数字组成;
  • 但一般很少使用下划线开头定义常规变量和函数,下划线开头用在特殊场景;
  • 通常变量、函数名全小写,类名首字母大写;
  • 变量、函数、类等的命名应当尽可能顾名思义,降低歧义,增加可读性;
  • 降低硬编码,更多用变量常量代表;

PEP8

  • Python代码风格优雅的定义

条件语句

if a:
    # 代码块
elif b:
    # 代码块
...
else:
    # 代码块

循环语句

while a:  # 当a为真时执行代码
    # 代码块
    continue # 也可以通过continue结束本次循环
    break # 也可以通过break终止循环

for b_i in b: # b为可迭代对象,如列表、元组、字符串等,b_i为其中的每一个元素
    # 代码块
    continue # 也可以通过continue结束本次循环
    break # 也可以通过break终止循环 
  • for语句可以作用于迭代器;迭代器内部都需要实现__iter__方法。
  • 顺序、条件、循环可以相互嵌套,但循环直接放在条件中的情况比较少,一般过于复杂的代码会用函数包装;

lambda表达式

  • 用于代替极其简单的函数
  • 格式:lambda 参数: 返回
    lambda x,y=7: x+y

数据结构

基本数据结构

  • 整数(int)、浮点数(float)、字符串(str)、布尔值(bool)
    base_type = [10, 23.4, 'sdfh32h45', True, False]
  • 可以通过其它类型合适的数据相互初始化,如
    print(int('23')) # 23

序列类型数据结构

  • 字符串:由连续的字符组成;整个都不能改变,改变需要新建对象;
  • 元组:由连续的任意对象组成,存放的是这些对象的引用;元组存放的引用不能边变,但是引用指向的内容可以变;
  • 列表:由连续的任意对象组成,存放的是这些对象的引用;列表存放的引用也可以变;
    a = 'ahdk432'
    b = (2, 6, '45', [4,'78'])
    c = ['gs', 4, 7, [34, '56']]
    sequence_type = [a, b, c]

字符串str

常见操作

  • $in/not in$ 判断成员关系;
  • +连接两个字符串;
  • *可以对字符串进行重复;
  • $[::]$,索引、切片操作;
  • $.strip()$去掉开头和末尾的字符

替换

print('可以在%s,以及%s,通过替换的方式得到所需字符串' % ('这里', '这里...等'))
not_trans = r'在字符串前加上r,可以指定字符串不转义,如\n等'

元组tuple

  • 相比list,更多的是用在不需要改变的场景,通过元组可以防止更改;

列表list

列表list是Python中的一个强大的数据结构,本质上是一个可以动态调整大小的ArrayList,list存储数据是在一个数组中存储元素的地址,地址实际指向的元素可以是很多种形式:数字、布尔、字符串、元祖、链表。
创建

  1. 用中括号$[]$包裹元素直接生成,元素使用逗号分隔;
  2. 用$list()$方法,将其它数据结构(字符串、元组、range函数等)转化成列表;
  3. 列表生成式/列表解析式/列表推导式,生成列表。

扩充

  1. $append()$在尾部添加元素;
  2. $insert(k,value)$在指定位置添加元素;
  3. $+$和$list_1.extend(list_2)$将两个链表拼接成一个新列表。

删除&销毁

  1. $del$ $list[m]$;
  2. $remove(value)$删除第一个匹配项;
  3. $pop(m)$删除指定位置元素;
  4. $clear()$清空;
  5. $del$ $list$销毁。

切片

  • $[i:i+n:m]$:从第i位开始至i+n位,不包括i+n位,每隔m位取一个。
  • 默认值$[0:length:1]$。
  • 值都可以大于列表长度,取不到就是空列表,不会越界报错。
  • 从0开始索引,左闭右开区间使得切片很优雅。
    step可以是负数,代表从后往前取,这种情况是先翻转再看索引来截取。
a1 = [1, 2, 'f']
a2 = list('asdfgjsld')
a3 = [2*i for i in range(10)]
print(a1, a2, a3)

a1.append(4)
a1.insert(5, 'asd')
a4 = a1+a2
a2.extend(a1)
print(a1, a2, a4)

del a1[0]
a1.remove(4)
a1.pop(-1)
a2.clear()
del a4
print(a1, a2)

其它操作

  1. $len(list)$获取元素个数。
  2. $count()$统计指定元素个数。
  3. $max(list)$统计元素最大值(要求元素类型相同才可比较,数值类型、字符串等直接比较,其它类型比较id)
    a=[2,4,5,6]
    max(a)
    out:6
    a=['dvs','vsvd','be','dfbeab']
    max(a)
    out:'vsvd'
  4. $min(list)$与$max$类似,比较正好相反。
  5. $index()$获取指定元素索引(第一个匹配项)
  6. $reverse()$翻转列表
  7. $copy()$浅拷贝
  8. 深拷贝
    import copy
    copy.deepcopy(list)
  9. $sort()$原地排序
  10. $sorted(list)$生成新列表

列表生成式&生产器表达式

l=[x*2 for x in range(5)] # 列表生成式,4以内整数的2倍数
g=(x*2 for x in range(5))# 生成器表达式

type(l)# 结果:<type 'list'>
type(g)# 结果:<type 'generator'>

print(l)# 结果:[0,2,4,6,8]
print(g)# 结果:<generator object at 0x000002173F0EBC50>
next(g)# 0
next(g)# 2
next(g)# 4
next(g)# 6
next(g)# 8
next(g)# Traceback (most recent call last): ....StopIteration
for x in g:
    print(x,end=' ')# 结果:0 2 4 6 8

有时候不需要同时使用所有数据的时候,使用生成器表达式会更节省空间,当然也有其它方式来替代。

yield

# 计算斐波那契数列的生成器
def fibon(n):
    a=b=1
    for i in range(n):
        yield a # 使用yield
        a,b=b,a+b

g=fibon(1000000)
next(g)# 1
next(g)# 1
next(g)# 2

字典dict

  • 底层是hash表,是一个个的$(key, value)$对;
  • key要求是可以进行hash计算的元素,对value则限制较少;
    dict1 = dict()
    dict1['name'] = 'wan chuan'
    dict1['age'] = 24
    dict1.keys() # 是key的list
    dict1.values() # 是value的list
    dict1.items() # 是(key, value)元组的list

字典推导式

d={x:x*2 for x in range(5)}

函数

定义&参数

  • 通过指定参数名字,可以变化参数的先后位置,但一般不建议变位置;
  • 默认参数可以不输入
    # c,d是可变长参数,c是list形式,d是字典形式
    def fun_name(a, b=1, *c, **d):
        print(c)
        print(d)
        if b == 1: 
            return a 
        else:
            return a**b
    
    print(fun_name(3))
    print(fun_name(3, 2))

变量作用域

  • 在函数中出现与外部同名的变量,会出现两个备份,在函数内使用内部局部变量;
  • 通过在函数内的变量前加上global,可以指定函数内的变量为全局变量,以影响函数外;

闭包

  • 实现内部函数调用外部变量
  • 可以得到带变量/状态的函数,这个状态可以是函数
    # 得到一个任意数量的累加器
    def counter(*c):
        if not c:
            cnt = [0]
        else:
            cnt = [i for i in c]
        def add_one():
            for i in range(len(cnt)):
                cnt[i] += 1
            return cnt
        return add_one
    f = counter(1,7,3)
    print(f())
  • 考虑到变量有不同的层次,因此闭包也可以多层嵌套,得到更加抽象的闭包

装饰器

  • 装饰器通过闭包得到,简单说是把函数包一层;

    # 得到一个计时装饰器
    def timer(func):
        def wrapper(*a,**b):
            start_time = time.time()
            func(*a,**b)
            end_time = time.time()
            print('time is %s' % (end_time-start_time))
        return wrapper
    
    @timer
    def do_something(n,show='null'):
        time.sleep(n)
        print(show)
    do_something(2,'hello world')
    
    # 也可以将@的形式写为:
    def do_something(n,show='null'):
        time.sleep(n)
        print(show)
    do_something = timer(do_something)
  • 装饰器还可以带参数,如decorator(arg1, arg2)意味着它会返回一个正常的装饰器

  • 装饰器还可以是类的形式,如下代码同样实现了装饰器的功能,它将代码分为了初始化和执行两个部分。

    class myDecorator(object):
        def __init__(self, fn):
            print("inside myDecorator.__init__()")
            self.fn = fn
    
        def __call__(self):
            self.fn()
            print("inside myDecorator.__call__()")
    
    @myDecorator
    def aFunction():
        print("inside aFunction()")
    
    aFunction()
  • 装饰器还可以根据需要改变参数设置

  • 通过functools的wraps可以让装饰后的函数更加像原函数一些

    from functools import wraps
    def hello(fn):
        @wraps(fn)
        def wrapper():
            print("hello, %s" % fn.__name__)
            fn()
            print("goodby, %s" % fn.__name__)
        return wrapper
    
    @hello
    def foo():
        '''foo help doc'''
        print("i am foo")
        pass
    
    foo()
    print foo.__name__ #输出 foo
    print foo.__doc__  #输出 foo help doc
  • 装饰器还可以给函数加上缓存

    from functools import wraps
    def memo(fn):
        cache = {}
        miss = object()
    
        @wraps(fn)
        def wrapper(*args):
            result = cache.get(args, miss)
            if result is miss:
                result = fn(*args)
                cache[args] = result
            return result
    
        return wrapper
    
    @memo
    def fib(n):
        if n < 2:
            return n
        return fib(n - 1) + fib(n - 2)
  • 装饰器注册回调函数

    class MyApp():
        def __init__(self):
            self.func_map = {}
    
        def register(self, name):
            def func_wrapper(func):
                self.func_map[name] = func
                return func
            return func_wrapper
    
        def call_method(self, name=None):
            func = self.func_map.get(name, None)
            if func is None:
                raise Exception("No function registered against - " + str(name))
            return func()
    
    app = MyApp()
    
    @app.register('/')
    def main_page_func():
        return "This is the main page."
    
    @app.register('/next_page')
    def next_page_func():
        return "This is the next page."
    
    print app.call_method('/')
    print app.call_method('/next_page')
  • 装饰器还可以把函数异步化

    from threading import Thread
    from functools import wraps
    
    def async(func):
        @wraps(func)
        def async_func(*args, **kwargs):
            func_hl = Thread(target = func, args = args, kwargs = kwargs)
            func_hl.start()
            return func_hl
    
        return async_func
    
    if __name__ == '__main__':
        from time import sleep
    
        @async
        def print_somedata():
            print 'starting print_somedata'
            sleep(2)
            print 'print_somedata: 2 sec passed'
            sleep(2)
            print 'print_somedata: 2 sec passed'
            sleep(2)
            print 'finished print_somedata'
    
        def main():
            print_somedata()
            print 'back in main'
            print_somedata()
            print 'back in main'
    
        main()

上下文管理器

  • 在文件操作后需要对文件进行关闭,不能漏掉,可以通过with as语句,更加优雅、安全的达到目的;

常用内建方法

文件

  • 增删改查等:Python中将文件、网络、IO等都抽象为了文件,因此操作方法比价通用简洁;与Linux类似;
    f = open('file.txt', 'w') # mode='w'/'r'
    f.write('这里需要是字符串')
    f.close()
    
    f = open('file.txt', 'r') # mode='w'/'r'
    print(f.readline()) # 读一行
    print(f.readline(m)) # 读m个字符
    print(f.tell())  # 文件指针的位置
    print(f.readlines()) # 列表形式读全部,每行一个元素
    f.seek(n, whence=0)  # 将文件指针的位置移到whence+n,即可以从指定位置开始偏移
    print(f.read()) # 全部读
    f.close()
    
    # .close()如果漏掉是严重错误,通过下面的with as语句,可以不用写.close(),相当于隐式的包含了
    with open('file.txt', 'r') as f:
        f.read()
  • os库:
    import os, pathlib
    
    os.path.abspath('.') # 获取绝对路径
    os.path.exists('/Users/wanc/Desktop')
    os.path.isdir('/Users/wanc/Desktop')
    os.path.isfile('/Users/wanc/Desktop')
    os.path.join('/Users/wanc', 'Desktop')
    
    p = pathlib.Path('.')
    p.resolve()
    p = pathlib.Path('./tmp/a/')
    pathlib.Path.mkdir(p, parents=True)

异常处理

  • 各种异常都是Exception的子类,所以Exception可以捕获所有异常
    try:
        # 需要监控的代码
    except (ValueError, KeyError, AttributeError):
        # 捕获到特定异常时的处理
    except Exception as e:
        # 捕获到所有异常时的处理
        print(e)
    finally:
        # 无论是否异常都会执行的代码,如关闭文件等

高阶函数

from functools import reduce
filter(fun, iterable) # 根据fun得到True/False,对iterable的值进行过滤
map(fun, *iterables)  # 对iterables中的值用根据fun进行处理
reduce(fun, sequence) # 根据fun对sequence中的值进行聚合
zip(iter1[,iter2[...]]) # 将多个iter合并成一个iter,返回列表迭代器
sorted(iterable, key=fun) # 通过key的函数来选择排序的key,以实现对复杂对象的排序

正则化表达式 re

  • 正则化表达式匹配:用特殊的符号表达特殊形式的字符串,可以看成是对字符串的压缩或泛化
    # .任意单个字符
    # *前面的字符出现0到多次
    # +前面的字符出现1到多次
    # ?前面的字符出现0或1次
    # ^以后面的字符开头
    # $以前面的字符结尾
    # {n}前面的字符出现n次
    # {m,n}前面的字符出现m到n次,左右闭区间
    # [s]匹配括号中的任意一个字符 , [12378], [0-9], 
    # |左或右的字符
    # \d匹配一串数字,相当于[0-9]
    # \D匹配不包含数字
    # \s匹配一串小写字符,[a-z]
    # ^$ 空行
    # .*? 不使用贪婪模式,?是控制.*只匹配第一个符合的部分
    # ()通过用()将一部分扩起来,匹配后可以通过.group(n)取出其中的部分,或通过.groups(n)取得所有;
    import re
    
    p = re.compile('3{4,5}') # 正则表达式
    print(p.match('3333'))  # 查看是否匹配,要求从前往后开始匹配
    p = re.compile('^5(a|c)(.*)3$')
    print(p.match('5caafefwe42643333').groups())
  • 正则化表达式搜索:search,不要求从第一个字符开始匹配
  • 多次搜索:findall,避免search只找第一个
  • 替换:$sub(被替换的字符,替换的字符,原字符)$
    p = re.compile('3{4,5}') 
    print(p.search('ghakhs3333')) 
    print(p.findall('ghakhs3333fsadf3333jnkjn3333')) 
    print(re.sub('3{4,5}','新的','ghakhs3333'))

时间日期

import time, datetime

time.time()  # 秒数
time.localtime()  # 各种日期时间类
time.strftime(r'%Y-%m-%d %H:%M:%S')  # 结构化输出,选择输出哪几个量

nowtime = datetime.datetime.now()   # 当前时间
settime = datetime.datetime(2021,10,19)  # 设定时间
deltatime = datetime.timedelta(minutes=10)  # 偏移时间
print(nowtime - deltatime, settime + deltatime)  # 时间计算

数学

  • math
  • random
    print(math.cos(3), math.sin(4),random.randint(1, 5),random.choice([3,5,'gs',[4,5]]))

面向对象

class Class_name1():
    def __init__(self,att1,att2):
        '''
        构造函数,初始化
        '''
        self.att1 = att1
        self.__att2 = att2 # 通过双下划线,可以将属性隐藏起来,避免外部直接访问,即类的封装
    
    def func1(self):
        pass

    def __enter__(self): # 初始化前执行
        pass

    def __exit__(self, exc_type, exc_val, exc_tb): 
        # 使用with语句时,在代码块执行结束时执行
        # exc_tb是捕获的with语句执行期间的异常
        pass

class Class_name2(Class_name1):   #Class_name2从Class_name1继承
    def __init__(self,att1,att2,att3,att4):
        super().__init__(att1,att2) # 调用父类的初始化方法初始化父类定义的属性
        # Class_name1.__init__(att1,att2) 也可以用这种方式进行父类属性初始化,当从多个父类继承时,只能用这种方法
        self.att3 = att3
        self.att4 = att4
        # self.att1 = att4 如果子类定义了父类已经定义的变量或函数,则会覆盖/重写,即多态
    
    def func2(self):
        pass

并发

多线程

import threading

def my_thread(arg):
    pass

threads = []
for arg in args:
    t = threading.Thread(target=my_thread,args=(arg)) # 创建线程,并设置执行方法和参数
    t.start()  # 启动线程,开始执行
    threads.append(t)

for t in threads:
    t.join() # 分别等待所有线程都运行结束

队列

import queue   # 队列库,可以实现生产者消费者模型
q = queue.Queue()
q.put(3)  # 加入队列
q.get()   # 从队列中取出
q.task_done() # 提示已经取出元素并执行完,方便join判断是否结束
q.join() # 等待队列被消耗完

常用库

模块

  • 导入模块:
    from ab import cde as f
    f.func() 
  • 制作模块:将方法、类等写成py文件或者用文件夹组织;

JSON

  • JSON 的全称是 JavaScript Object Notation,是一种轻量级的数据交换格式。最初,JSON 只是JavaScript 的子集,但由于其简单易用而迅速走红。
  • 现今大部分编程语言都支持对 JSON 的解析与生成,而近些年异军突起的 NoSQL 数据库也多参照 JSON来设计数据存储格式,例如 Mongodb 的BSON(Binary JSON)。
  • JSON 有以下六种数据类型:number、boolean、string、null、array、object。前三种很好理解,第四个 null 对应 Python 的 None,最后两种,对应 Python 的列表和字典。
{
  "name":"小明",
  "age":14,
  "gender":true,
  "grade":null,
  "skills":[
  "JavaScript",
  "Java",
  "Python"
  ]
}
  1. json.dumps() 把 Python 对象序列化;
  2. json.dump() 先序列化,然后将内容存入文件
import json
d=dict(name='Tom',age='8',score=88)
json.dumps(d) 
#'{"name": "Tom", "age": "8", "score": 88}'
with open('test.json','w') as f:
    json.dump(d,f)
  1. json.loads() 从内存中读取内容解析;
  2. json.load() 从文件中读取内容解析
import json
d=dict(name='Tom',age='8',score=88)
tom_json=json.dumps(d)
json.loads(tom_json)
#{'age':'8','name':'Tom','score':88}
with open('test.json','r') as f:
    print(json.load(f))
#{'name':'Tom','age':'8','score':88}

ujson可以代替json,且速度更快。

numpy

  • Numpy基于c语言实现,因此十分高效,pandas又基于numpy,提供更加丰富的功能。
  • 生成ndarray数据的三种主要方式:
    • 通过Python内置list转化:np.array(list) ,可以用dtype设置默认数据类型;
    • 直接用numpy生成:np.arange(m), np.zeros(), np.ones(), np.random.rand*(), np.empty(), np.eye(), np.linspace()
    • 通过文件导入:如np.loadtxt('cdscacc.csv',),可以选择分隔符、使用那些行列等。
  • Ndarray是数组,所以无论多少维都用一个中括号[start:end:step]完成索引、切片,而list可以层层嵌套,因此多层索引需要多个中括号;这种差别本质上是因为Ndarray无论多少维都是一个Ndarray,list则不是,它是不同层的。
  • 调用方法有两种途径,np.fun(self),self.fun()
  • 常用基本方法:(arg)min,(arg)max,(cum)sum, diff差分, nonzero输出非零位置索引, median,mean,variance,sort, reshape
  • np.sort()生成新的排序后数组,self.sort()是在原数组基础上操作, reshape等也是。
  • 数学运算:np.sin(),cos(),tan(),……
  • np.linspace(start,end,number)用于生成等间隔序列。
  • ndarray常用属性:
    • ndim:维度;
    • shape:形状;
    • size:元素数量;
    • dtype:元素类型,可以用self.astype()来设置元素类型;
  • ndarray的一个强大的筛选功能是直接比较并返回同样大小并有true/false组成的数组,如:np.array(list)>4,还可以矩阵与矩阵比较,只要符合广播机制要求,可以形状不一样。np.any(), np.all(), 可以用于判断返回的bool数组是否有True或全都是True
  • ndarray直接相乘是元素乘,np.matmul()是矩阵乘, np.dot()可以适应多种乘法。
  • ndarray相乘的时候会使用广播机制
  • np.transpose(), self.T转置。
  • np.clip()截尾,self.flatten()铺平。
  • np.concatenate((a,b,….,n),axis=)指定维度合并, np.split()分割。
  • Python中大量使用指针,因此许多操作都只是复制指针值,并没有真正的拷贝数据,这样容易出现一个地方修改了,其它地方也跟着变的情况,因此如果需要修改值同时又要保留以前内容的话可以尝试深度拷贝,如self.copy()。基本上任何一个对数据修改后返回的运算都是创建了新值。
  • np.unique()可以找出一个数组中的元素,可以看成去掉重复。

Pandas

  • 如果把numpy看成是加强版的列表listpandas就像是加强版的字典dict,为数据加上了许多标签。
    pd.Series([23,43,24,np.nan,42,42])
    0    23.0
    1    43.0
    2    24.0
    3     NaN
    4    42.0
    5    42.0
    dtype: float64; 
pd.date_range('2020-05-02',periods=4)
DatetimeIndex(['2020-05-02', '2020-05-03', '2020-05-04', '2020-05-05'], dtype='datetime64[ns]', freq='D');
pd.DataFrame(np.random.randint(0,100,(23,3)),index=np.arange(10,33),columns=['d','f','w'])
  • pandas的操作方法大都是生成新的对象并返回。
  • DataFrame中的index指示数组(字典)的行索引,columns代表列索引,不指定则使用默认自然数,也可以指定。
  • 如果用字典生成DataFrame,默认字典的key对应columns
  • DataFrame常用属性:
    • dtypes:每一列的属性;
    • indexDataFrameindex
    • columnsDataFramecolumns
    • values:用矩阵形式输出内容;
    • T:转置;
  • DataFrame常用方法:
    • describe():获取每一列的计数、均值、标准差等等信息;
    • sort_index():可以按照indexcolumns排序;
    • sort_values(by=):选定某一特征排序。
  • DataFrame常见索引方式:
    • df[‘columns’], df.columns进行列选择;
    • df[m:n]按行索引;
    • df.loc[m:n ,[‘columns’,’’]]:按标签进行选择,需要同时考虑行和列;
    • df.iloc[:,:]:按位置进行索引,不连续的时候可以用[‘’,’’,…,’’]代替:。
  • df[df[]><==data]等方式筛选。
  • df.dropna()可以设置以多种方式来去掉有缺失值的行或列。
  • df.fillna()可以用于填入缺失值。
  • df.isnull()返回各个位置是否为空。
  • 通常用read_*()to_*()来读写文件。
  • pd.concat([a,b,…,c],axis=,ignore_index=)可以用于连接多个DataFrame
    • axis:指定连接维度;
    • ignore_index:是否忽略原行索引;
    • join:用于指定索引不同时的处理方式,inner:取交,outer:并;
  • 也可以用append来实现concat的功能。
  • pd.merge(left,right)也可以用于合并:
    • how: str = 'inner',指定合并的方式
    • on=None,指定用哪个公共的列(关键字)合并
    • left_on=None,分别指定on
    • right_on=None,分别指定on
    • left_index: bool = False,是否考虑左边的index
    • right_index: bool = False,是否考虑右边的index
    • suffixes=('_x', '_y'),如果连接的两个有相同的key,为了避免重复可以用这个加上后缀;
    • indicator: bool = False,增加一列说明数据来源,左右都;
  • 可以配合matplotlib进行显示,并直接使用自带的plot等方法。
  • 选中某一列使用self.value_counts()可以查看该列的分布数量。
  • df.melt()df.pivot()逆转操作函数,将列名转换为列数据(columns name → column values),重构DataFrame.如果说 df.pivot() 将长数据集转换成宽数据集,df.melt() 则是将宽数据集变成长数据集。

matplotlib

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(5,3),dpi=100)
plt.plot([1,2,3,5,6,7])
plt.hist([1,2,3,5,6,7])
plt.scatter(x,y)
plt.show()

urllib/requests/BeautifulSoup

from urllib import request, parse
import requests
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'
response = request.urlopen(url, timeout=1)
response.read().decode('utf-8')

response = requests.get(url)
response = requests.post(url)
response.text
response.json()

soup = BeautifulSoup(response.text, 'lxml')
soup.prettify()
soup.title.string
soup.p
soup.a

heapq

  • heapq.heapify('list'):将一个list堆化,默认最小堆,最大堆可以将元素乘以-1。
  • heapq.heappush('list', item):向堆中添加一个元素,继续维持小根堆。
  • heapq.heappop('list'):弹出堆顶(最小)元素,继续维持小根堆。
  • heapq.heappushpop('list', item):先push,再pop。
  • heapq.heapreplace('list', item):先pop,再push。
  • heapq.nlargest(n, iterable, key=None):取前n大。
  • heapq.nsmallest(n, iterable, key=None):取前n小。

bisect

  • bisect.bisect_left('list',x):在升序list中插入一个x,使得列表仍然有序,返回插入位置,如果有列表中有x,则插入位置在原x左侧,即原x的位置。
  • bisect.bisect_right('list',x):同上,如果有列表中有x,则插入位置在原x右侧,即原x的位置+1。

pytorch

基础操作

view & reshape

  • view:只改视图/索引方式,不会增加数据副本,如果遇到不连续的情况就报错;
  • reshape:改视图/索引方式,必要时增加数据副本,如果数据连续只改视图/索引方式,如果遇到不连续就新增数据副本;
  • 转置会带来数据存储不连续;
x = torch.tensor([1,2,3,4,5,6])  # 原数据连续存储
tensor([1, 2, 3, 4, 5, 6])

y = x.view(3, 2)  # 改变视图
tensor([[1, 2],
        [3, 4],
        [5, 6]])

y = y.view(2, 3)  # 改变视图
tensor([[1, 2, 3],
        [4, 5, 6]])

y = y.t()       # 转置后不再连续
tensor([[1, 4],
        [2, 5],
        [3, 6]])

y.view(2,3)     # 无法改变,报错

z=y.reshape(2,3)   # 改变视图,增加副本
tensor([[1, 4, 2],
        [5, 3, 6]])
z[0,0] = 0          # 新副本不影响原数据
x
tensor([1, 2, 3, 4, 5, 6])

y[0,0] = 0           # view不增加副本,影响原数据
x
tensor([0, 2, 3, 4, 5, 6])

d = x.reshape(2,3)      # 改变视图,不增加副本
tensor([[0, 2, 3],
        [4, 5, 6]])
d[0,1] = 0           # 影响原数据
x
tensor([0, 0, 3, 4, 5, 6])

广播

  • 形状不同的tensor操作可能会触发广播机制,以满足运算要求

Tensor和NumPy相互转换

# 共享内存的方法,快速
torch.from_numpy() 
.numpy()

# 不共享内存的方法,需要拷贝数据
torch.tensor()

CPU和GPU相互转换

# 改变位置的同时指定数据类型
.to("cpu", torch.double)
.to("cuda", torch.float)

自动求梯度

# 从该位置开始反向传播
.backward()
# 配置tensor是否需要追踪梯度
.requires_grad
# 梯度保存位置
.grad
# 该部分操作不追踪
with torch.no_grad()

tensorflow


文章作者: 万川
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 万川 !
  目录