学习 Python3 语言

Conda in Action

conda 命令

创建名为 tensorflow 的 conda 环境

conda create -n tensorflow pip python=3.5 

激活 conda 环境

source activate tensorflow

退出 conda 环境

source deactivate

删除 conda 环境

conda remove -n env_name --all

列出虚拟环境

$ conda env list

以安装 TensorFlow 为例

$ conda create -n bert pip python=3.6
$ source activate bert
$ pip install --ignore-installed --upgrade https://mirrors.tuna.tsinghua.edu.cn/tensorflow/linux/cpu/tensorflow-1.10.0-cp36-cp36m-linux_x86_64.whl

删除 anaconda

conda install anaconda-clean
anaconda-clean --yes
rm -rf ~/miniconda

源(仓库镜像)

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/

国内源的地址

名称 地址
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣 http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/

使用方法

$ pip3 install {package name} -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

reference

https://www.tensorflow.org/install/install_windows#installing_with_anaconda

virtualenv

创建独立python环境

virtualenv env_name -p /usr/bin/python3

--no-site-packages 已被移除

激活独立环境

source env_name/bin/activate

退出独立环境

deactivate

删除不需要的独立环境

rm -rf env_name

第一行

Python3 开头的一行到底应该怎么写?
查阅 Google 的代码仓库,找到若干以 Python3 为主的 repo,选择比较流行的库 Trax 作为范本。随机抽取某个脚本(https://github.com/google/trax/blob/master/trax/trainer.py),该脚本的头部如下所示:

# coding=utf-8

所以今后 python3 文件的开头都将参照该规范。

标准的函数声明

LeetCode 的 Python3 模板具有较好的编码规范,如下所示是一个编码风格良好的函数声明:

class Solution:
    def shortestSubarray(self, A: List[int], K: int) -> int:
        pass

该函数接收两个参数,参数的类型分别为 List[int] 和 int,函数的返回值为 int
ref:https://leetcode-cn.com/problems/shortest-subarray-with-sum-at-least-k/

构造HTTP请求

def get_html(url):
    headers = {
        'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)'
                      r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
        'Connection': 'keep-alive'
    }
    req = request.Request(url, headers=headers)
    page = request.urlopen(req).read()
    page = page.decode('utf-8')
    return page

字符串前缀的语义

f-string

f-string 是 python3.6 之后版本添加的,称之为字面量格式化字符串,是新的格式化字符串的语法。
之前我们习惯用百分号 (%):

>>> name = 'Runoob'
>>> 'Hello %s' % name
'Hello Runoob'

f-string 格式话字符串以 f 开头,后面跟着字符串,字符串中的表达式用大括号 {} 包起来,它会将变量或表达式计算后的值替换进去,实例如下:

>>> name = 'Runoob'
>>> f'Hello {name}' # 替换变量

>>> f'{1+2}' # 使用表达式
'3'

>>> w = {'name': 'Runoob', 'url': 'baidu.com'}
>>> f'{w["name"]}: {w["url"]}'
'Runoob: baidu.com'

u-string

在Python2中,普通字符串是以8位ASCII码进行存储的,而Unicode字符串则存储为16位unicode字符串,这样能够表示更多的字符集。使用的语法是在字符串前面加上前缀 u。
在Python3中,所有的字符串都是Unicode字符串。所以在python3中,下面的两个字符串等价:

>>> a = 'abc'
>>> b = u'abc'
>>> a is b
True

b-string

在 python3 中,字符串前缀 b 意味着将字符串存储为 ASCII 码,无法存储中文。每个字符由底层中的一个字节(8位)来表示。

r-string

在 python3 中,字符串前缀 r 意味着将字符串中的所有字符都视为普通字符,所以主要解决的是转义字符的和特殊字符的问题。

matplotlib

折线图

from matplotlib import pyplot as plt
plt.title("Matplotlib demo") 
plt.xlabel("x axis caption") 
plt.ylabel("y axis caption") 
plt.plot(x, y1)  # 第一条折线
plt.plot(x, y2)  # 第二条折线
plt.show()

logging

python3 内置日志函数包

import logging
logging.basicConfig(
    format='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
    datefmt='%m/%d/%Y %H:%M:%S',
    filemode='w',
    level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info("[content]%s" % (html))

argparse

首先,需要导入 argparse 库,并且声明一个参数解析器。

import argparse
parser = argparse.ArgumentParser()

其次,参数分为两种,一种是位置参数,一种是可选参数。位置参数是运行程序的必填项。

# Positional arguments
parser.add_argument("train", type=str,
 help="training data path, i.e. ctb8 and 1998")
parser.add_argument("embedding", type=str,
 help="word embedding path")

第二种是可选参数,区别在于加入了“--”前缀。

# Optional arguments
parser.add_argument("--sep", default=0, type=int,
 help="the separators of training data, split token and label, 0 for _(default), 1 for /")
parser.add_argument("-ml", "--max_len", default=50, type=int,
 help="length of training data sequence, default is 50")
parser.add_argument("-e", "--epochs", default=3, type=int)
args = parser.parse_args()

最后,获得用户的输入很简单,如下所示。

seperator = '_' if args.sep is 0 else '/'

Ref: https://docs.python.org/3.7/howto/argparse.html

numpy

pad

import numpy as np
x = np.random.normal(size=(2,2))
np.pad(x, ((0,1), (1,0)), 'constant')

在填充(pad)前,x 的值如下所示:

array([[-1.04965022, 1.50657074],
       [-0.95876126, -0.46918995]])

填充后,x 的值如下所示:

array([[ 0. , -1.04965022, 1.50657074],
       [ 0. , -0.95876126, -0.46918995],
       [ 0. , 0. , 0. ]])

pad 有三个参数:

  1. 待填充的 numpy ndarray
  2. 每个维度上 before 和 after 的填充数量
  3. 填充值

第二个参数需要着重介绍。array_like,每个 tuple 表达了在该维度上的 before 填充数和 after 填充数。

(
    (上, 下), # 第一个维度
    (左, 右), # 第二个维度
    ......
)

os

walk

os.walk 函数可以遍历指定路径

import os

# root: os.walk 函数第一个参数 path 的延续
# paths: 当前目录下的文件夹
# files:当前目录下的文件
for root, paths, files in os.walk(path, topdown=False):

    for name in files:
        print(os.path.join(root, name))
        
    for path in paths:
        print(os.path.join(root, path))

zip 反函数

python3中,zip函数的反函数是:

lst1, lst2 = zip(*zipped_list)

解释如下:

a = [1,2,3]
b = [4,5,6]
zipped_list = zip(a,b)
# zipped_list = [(1,4), (2,5), (3,6)]

unziped_list = zip(*zipped_list)
# unziped_list = [(1, 2, 3), (4, 5, 6)]

string

find

Python3中的字符串查找函数的底层算法采用了 Boyer–Moore–Horspool 算法。不仅是 find 函数,其实 index, split, replace, __contains__, 和 SRE prefix scanner 也采用了 Boyer–Moore–Horspool 算法。

s = "Hello World!"
s.find("World")

算法:Boyer–Moore–Horspool

时间复杂度:平均O(n),最坏O(kn),其中k是模式的长度,n是字符串长度。

算法:Knuth–Morris–Pratt

时间复杂度:平均O(n+k),最坏O(kn),其中k是模式的长度,n是字符串长度。

Reference:

[1] https://en.wikipedia.org/wiki/Boyer–Moore–Horspool_algorithm

[2] https://github.com/python/cpython/blob/master/Objects/stringlib/fastsearch.h#L5

[3] http://effbot.org/zone/stringlib.htm

[4] https://stackoverflow.com/questions/681649/how-is-string-find-implemented-in-cpython

[5] https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm

分层采样

scikit-learn 的 train_test_split 函数提供了分层采样的功能:

x_train, x_test, y_train, y_test = train_test_split(
	x, y, 
	test_size=0.33, 
	random_state=42,
	stratify=y)  # 若要分层采样,必须设置 stratify 

文件模板

经过长期的总结与阅读优秀源码,基于组件的文件模板如下。

Script

# encoding=utf-8

import os
import sys
import argparse
import logging
import configparser

__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.abspath(os.path.join(__dir__, '..')))

# from Lib.TextAbstract import TextAbstract
# from Lib.Stock import Stock


def parse_argv():
    parser = argparse.ArgumentParser()
    parser.add_argument("config", type=str, help="configuration file path")
    parser.add_argument("--log", type=str, default=None, help="log file path")
    return parser.parse_args()


def run(argv, config):
    pass


def main():
    argv = parse_argv()

    config = configparser.ConfigParser()
    config.read(argv.config)

    logging.basicConfig(
        filename=argv.log,
        format='%(asctime)s - %(levelname)s - %(name)s - %(msg)s',
        datefmt='%Y-%m-%d %H:%M:%S',
        level=logging.INFO)

    run(argv, config)


if __name__ == '__main__':
    logger = logging.getLogger(__name__)
    main()

HTTP Service

# encoding=utf-8


import os
import sys
import uvicorn
from fastapi import FastAPI

__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.abspath(os.path.join(__dir__, '..')))


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("config", type=str, help="configuration file path")
    parser.add_argument("--log", type=str, default=None, help="log file path")
    parser.add_argument("--host", type=str, default="0.0.0.0", help="host")
    parser.add_argument("--port", type=int, default=8080, help="host")
    return parser.parse_args()
    

def supplement(app: FastAPI, config: ConfigParser) -> None:

    @app.on_event("startup")
    async def startup_event() -> None:
        app.state.redis = Redis()
        

    @app.on_event("shutdown")
    async def shutdown_event() -> None:
        app.state.redis.close()


def main(args, config):
    application = FastAPI()
    supplement(application, config)
    application.include_router(api_router)
    uvicorn.run(
        app=application,
        host=args.host,
        port=args.port
    )


if __name__ == '__main__':
    args = parse_args()

    config = configparser.ConfigParser()
    config.read(args.config)

    logging.basicConfig(
        filename=args.log,
        format='%(asctime)s - %(levelname)s - %(name)s - %(msg)s',
        datefmt='%m/%d/%Y %H:%M:%S',
        level=logging.INFO
    )
    
    main(args, config)

posted @ 2020-05-16 15:40  健康平安快乐  阅读(354)  评论(0编辑  收藏  举报