python 小技巧

5 minute read

Published:

开始写 python 之后才发现一堆不会的,有一点不会就查一点最后补充到这,未完待续。

输入输出

# 从标准输入读取一个行,并返回一个字符串(去掉结尾的换行符)
str = input("请输入:")

# 标准输出
# '\r' 可刷新当前行输出结果,当 i 有位数变化时可能出错,需要用 format 格式化输出
# end 指定结尾:'\n' 换行,'' 不换行
print('\r', i, end='')

format() 格式化函数

# 不设置指定位置,按默认顺序
print("{} {}".format("hello", "world"))        # 'hello world'

# 设置指定位置
print("{0} {1}".format("hello", "world"))      # 'hello world'

# 设置指定位置
print("{1} {0} {1}".format("hello", "world"))  # 'world hello world'

# 通过字典设置参数
print("名字: {name}, 地址: {url}".format(name="hello", url="world"))
 
# 通过字典设置参数
site = {"name": "hello", "url": "world"}
print("名字: {name}, 地址: {url}".format(**site))
 
# 通过列表索引设置参数
site = ['hello', 'world']
print("名字: {0[0]}, 地址: {0[1]}".format(site))  # "0" 是必须的

指定格式输出:

  • : 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。

  • ^, <, > 分别是居中、左对齐、右对齐,后面带宽度。

  • + 表示在正数前显示 +,负数前显示 -

  • b, d, o, x 分别是二进制、十进制、八进制、十六进制。

  • 可以使用大括号 {} 来转义大括号

print("{:.0f}".format(3.1415926))    # 3
print("{:.2f}".format(3.1415926))    # 3.14
print("{:+.2f}".format(3.1415926))   # +3.14
print("{:+.2f}".format(-3.1415926))  # -3.14

print("{:0^4d}".format(5))  # 0500
print("{:0>4d}".format(5))  # 0005
print("{:>4d}".format(5))   #    5
print("{:x<4d}".format(5))  # 5xxx

print("{:b}".format(11))    # 1011
print("{:x}".format(11))    # b
print("{:#x}".format(11))   # 0xb
print("{:#X}".format(11))   # 0XB

print ("0 is {}".format("good")) # {0} is good

时间

from datetime import datetime

total_starttime = datetime.now()

# your code here

total_endtime = datetime.now()
print('Total running time: ', (total_endtime - total_starttime).seconds, ' seconds! ')

now_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

tqdm 进度条

from tqdm import tqdm
for i in tqdm(range(100000)):
    pass

func(*args, **kwargs) 函数

这是 Python 函数可变参数 args 及 kwargs

*args 表示任何多个无名参数,它是一个 tuple

**kwargs 表示关键字参数,它是一个 dict

测试代码如下:

def foo(*args,**kwargs):
    print('args=',args)
    print('kwargs=',kwargs)
    print('**********************')

if __name__=='__main__':
    foo(1,2,3)
    foo(a=1,b=2,c=3)
    foo(1,2,3,a=1,b=2,c=3)
    foo(1,'b','c',a=1,b='b',c='c')

执行结果如下:

args= (1, 2, 3)
kwargs= {}
**********************
args= ()
kwargs= {'a': 1, 'c': 3, 'b': 2}
**********************
args= (1, 2, 3)
kwargs= {'a': 1, 'c': 3, 'b': 2}
**********************
args= (1, 'b', 'c')
kwargs= {'a': 1, 'c': 'c', 'b': 'b'}
**********************

** 字典传参

通过定义字典来传参数

def test(a, b=1, c=1):
    print(a + b + c)

kwargs = {'a':3, 'c':3}

test(**kwargs, b=2)

匿名函数 lambda

python 使用 lambda 来创建匿名函数

sum = lambda arg1, arg2: arg1 + arg2
print("相加后的值为: ", sum(10, 20))  # 30

装饰器

from functools import wraps
def use_logging(level):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % func.__name__)  # 输出 'f'
            elif level == "info":
                logging.info("%s is running" % func.__name__)  # 输出 'f'
            return func(*args, **kwargs)
        return wrapper
    return decorator

@use_logging(level="warn")
def f(x):
    """does some math"""
    return x + x * x

日志文件

使用 tee

# 将输出写入文件
python test.py | tee -a test.log

使用 logging

import logging

# 输出到标准输出流
# 配合以下命令使用可将输出写入文件
# python test.py | tee -a test.log
logging.basicConfig(stream=sys.stdout,
                    level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s:%(message)s',
                    datefmt='%m/%d %H:%M:%S')

# 直接输出到文件
logging.basicConfig(filename="test.log", filemode="a",
                    level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s:%(message)s',
                    datefmt='%m/%d %H:%M:%S')

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

使用 logger

import logging
import logging.handlers

logger = logging.getLogger("logger")

handler1 = logging.StreamHandler()
handler2 = logging.FileHandler(filename="test.log")

logger.setLevel(logging.DEBUG)
handler1.setLevel(logging.DEBUG)
handler2.setLevel(logging.DEBUG)

formatter = logging.Formatter(fmt="%(asctime)s %(levelname)s:%(message)s",
                              datefmt='%m/%d %H:%M:%S')
handler1.setFormatter(formatter)
handler2.setFormatter(formatter)

logger.addHandler(handler1)
logger.addHandler(handler2)

logger.debug('This is a customer debug message')
logger.info('This is an customer info message')
logger.warning('This is a customer warning message')
logger.error('This is an customer error message')
logger.critical('This is a customer critical message')

// 运算符

// 运算符执行地板除法(向下取整除),它会返回整除结果的整数部分

*np.dot()np.multiply() 区别

 listnp.arraynp.mat()
*error点乘叉乘
np.dot()一维内积,其他叉乘一维内积,其他叉乘叉乘
np.multiply()点乘点乘点乘

typedtypeastype 用法

名称描述用法
type()返回参数的数据类型type(a)
dtype返回数组中元素的数据类型a.dtype
astype()对数据类型进行转换a=a.astype(int)

enumerate() 函数

seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
	print i, element
"""
0 one
1 two
2 three
"""

zip() 函数

train_X = [0, 1, 2]
train_Y = ['one', 'two', 'three']
for (x, y) in zip(train_X, train_Y):
  print(x, y)
"""
0 one
1 two
2 three
"""

进制转换(二、八、十六进制的字符串)

普通方法

# 十进制转二进制
bin(18)  # '0b10010'

# 十进制转八进制
oct(18)  # '0o22'

# 十进制转十六进制
hex(18)  # '0x12'

# 二进制转十进制 
int('0b10010',2)  # 18

# 八进制转十进制 
int('0o22',8)     # 18

# 十六进制转十进制 
int('0x12',16)    # 18

指定位数

# 十进制转二进制字符串(二进制位数为 8,高位填充 0)
('{:0' + str(8) + 'b}').format(18)  # '00010010'

类型转换

# str 类型转 list
list('010')  # ['0', '1', '0']

# 将 list 中的 str 元素都转换为 int
list(map(int, ['0', '1', '0']))  # [0, 1, 0]

# 将 list 中的 int 元素都转换为 str
list(map(str, [0, 1, 0]))        # ['0', '1', '0']

# 将 list 类型(元素为字符串)转换为字符串
''.join(['0', '1', '0'])

__future__ 模块

Python提供了 __future__ 模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。

from __future__ import

查看函数说明

help(sum)

设置随机种子

注意:若多次设置随机种子,以最后一次为准!

def init_seeds(seed=0):
    random.seed(seed)
    np.random.seed(seed)
    
    os.environ['PYTHONHASHSEED'] = str(seed)
    
    torch.manual_seed(seed)
    
    if torch.cuda.is_available(): 
        torch.cuda.manual_seed(seed)
        torch.cuda.manual_seed_all(seed)
        torch.backends.cudnn.deterministic = True
        torch.backends.cudnn.benchmark = False

调用 linux 命令

import os
os.system("ls")

抛出异常

assert expression [, message]

assert 1==1								# 条件为 true 正常执行
assert 1==2								# 条件为 false 触发异常
assert 1==2, '1 不等于 2'	# 条件为 false 触发异常

函数调用的相对路径

# 返回的是当前工作目录,非当前的脚本文件目录,所以在函数调用中会出现相对路径出错的问题
print(os.getcwd())

# 获取当前脚本文件所在目录,然后根据这个目录来访问相对路径下的文件
file_path = os.path.dirname(__file__)

二维 list 创建

利用乘法来创建二维 list 时会导致后面几行其实是第一行的一个浅拷贝,它们的地址是一样的,给任意一个赋值其余的也会被赋值。

l = [[0] * 3] * 3								# 错误
l = [[0] * 3 for i in range(3)]		# 正确

t检验

from scipy.stats import ttest_ind_from_stats

ttest_ind_from_stats(mean1=1, std1=0.1, nobs1=5,
                     mean2=2, std2=0.2, nobs2=5)

argparse

import argparse
parser = argparse.ArgumentParser("introduction")
parser.add_argument("--a", type=str, default="test", help="help")
parser.add_argument("--b", type=int, default=1)
parser.add_argument("--c", type=float, default=0.1)
parser.add_argument("--d", action="store_true", default=False)  # 可不需要 default,store_true 默认 False
parser.add_argument("--d", action="store_false", default=True)  # 可不需要 default,store_false 默认 True
config = parser.parse_args()

查看某个库文件位置

import gym
gym.__file__

参考资料及致谢

廖雪峰-Python教程

菜鸟教程-Python 基础教程

python二进制、十进制、8进制、16进制转换

Python日志库logging总结-可能是目前为止将logging库总结的最好的一篇文章

Python 函数装饰器

python中在发生函数调用时出现的相对路径更改

python二维列表list赋值时整列重复赋值问题