学习 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 有三个参数:
- 待填充的 numpy ndarray
- 每个维度上 before 和 after 的填充数量
- 填充值
第二个参数需要着重介绍。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)