Python

发布于 2020 年 10 月 19 日 | 更新于 2022 年 03 月 29 日

安装

Anaconda

(已安装的)包提供的可执行文件(如pip),Ubuntu环境下位于Anaconda3/bin目录,Windows环境下位于Anaconda3\Scripts目录

就算不知道在哪,也可以通过python -m pip ...来执行,其中pip可以替换成其他包提供的的可执行文件

好用的包

pretty-errors

pip install pretty_errors

使报错内容更易读

配置:执行python -m pretty_errors,生成默认配置文件(查看已有配置文件的位置),在末尾添加自定义样式

pretty_errors.configure(
        separator_character = '*',
        filename_display    = pretty_errors.FILENAME_EXTENDED,
        line_number_first   = True,
        display_link        = True,
        lines_before        = 5,
        lines_after         = 2,
        line_color          = pretty_errors.RED + '> ' + pretty_errors.default_config.line_color,
        code_color          = '  ' + pretty_errors.default_config.line_color,
)

getch

pip install getch

读取单个字符(不用按回车结束)

from getch import getch, getche
key = getch()   # 无回显
key = getche()  # 有回显

# On Windows
import msvcrt
key = msvcrt.getch()
key = msvcrt.getche()

argparse 参数解析器

下划线

知乎

前导单下划线

定义私有成员。这是一种约定,没有强制性,理论上还是可以从外部访问,只是约定不应该从外部访问_开头的名字

通配符*从模块中导入所有名称默认不会导入带有前导单下划线的名称

因此,尽量避免使用通配符导入

前导双下划线

名称转写:双下划线开头,结尾最多一个下划线的名字__a_,会被自动转换成_类名__a_

ref

后缀单下划线

通常用于与关键字做区分,当有变量名与python关键字相同时,可以添加后缀单下划线(slice_)进行区分

None

判断list中的无效(None)元素:

if x[i] is not None:
    pass

函数参数

参数分类

  1. 对于形参(声明函数),可分为
    • 普通参数:既不是默认值参数,也不是可变参数;消耗一个位置或关键字参数
    • 可选参数optional:带默认值,必须位于普通参数后面;消耗一个位置或关键字参数
    • 可变参数:本质是一个容器(tuple, dict),包含任意多个参数;消耗所有未匹配的参数
  2. 对于实参(调用函数),可分为:
    • 位置参数:function(value1, value2, ...)
    • 关键字参数:function(keyword1=value1, keyword2=value2, ...)

*和**

  1. 声明函数时,写在形参前,表明该参数为可变参数,如*args**kwargs

    • args是一个元组(tuple),收集实参中所有未匹配位置参数

    • kwargs是一个字典(dict),收集实参中所有未匹配关键字参数

    参数名argskwargs只是约定成俗的缺省名,可改用其他可读性更高的名字

  2. 调用函数时,写在实参前,用于解包,将容器(tuple/list, dict)拆开,变成多个位置或关键字参数

参数顺序

def my_function(
    [普通参数], [可选参数], [*args],    # 这一行接收位置参数
    [普通参数], [可选参数], [**kwargs]  # 这一行接收关键字参数
):
    pass

由于实参的关键字参数必须放在位置参数后面,因此形参只有先接收位置参数,再接收关键字参数

my_function( [位置参数], [关键字参数] )

可变参数,必须定义在普通参数(也称位置参数、必选参数、选中参数等名称)以及默认值参数的后面,这是因为可变参数会收集所有未匹配的参数,如果定义在前面,那么普通参数与默认值参数就无法匹配到传入的参数(因为都收集到可变参数中了…………) 参考

判断变量是否为某种类型的实例

比较两变量的类型是否相同

函数原型isinstance(object, classinfo)

isinstance(x, int)

isinstance(x, np.ndarray)

isinstance(x, torch.float32)

模块&包

一个py文件被视为一个模块,含有__init__.py的文件夹被称为

语法

包/模块的概念

利用__init__.py对外提供类型、变量和接口,对用户隐藏各个子模块的实现。一个模块的实现可能非常复杂,你需要用很多个文件,甚至很多子模块来实现,但用户可能只需要知道一个类型和接口。就像我们的arithmetic例子中,用户只需要知道四则运算有add、sub、mul、dev四个接口,却并不需要知道它们是怎么实现的,也不想去了解arithmetic中是如何组织各个子模块的。由于各个子模块的实现有可能非常复杂,而对外提供的类型和接口有可能非常的简单,我们就可以通过这个方式来对用户隐藏实现,同时提供非常方便的使用。

参考

python中导入(import)要写相对于(项目)根目录的路径

循环导入

a.py导入b.py,同时b.py导入a.py,就会发生循环导入,导致引入失败并报错

《python核心编程》:

加载模块会导致这个模块被执行。也就是被执行模块的顶层代码将直接被执行。这通常包含设定全局变量以及类和函数的声明

一个模块只被加载一次,无论它被导入多少次。这可以阻止多重导入时代码被多次执行

eval

eval(expression[, globals[, locals]])

将参数(字符串)当作python语句来执行。

可以实现通过字符串调用类或方法。

逻辑运算(and/or)

返回值不是True或False,而是以两个运算数之一作为返回值

短路求值:只有当第一个运算数的值无法确定逻辑运算的结果时,才对第二个运算数进行求值。

and:前真返后,前假返前

or:前真返前,前假返后

模拟C语言的三目运算a ? b : c,如下:

a and b or c

f-string

f-string在功能方面不逊于传统的%-formatting语句str.format()函数,同时性能又优于二者,且使用起来也更加简洁明了,因此对于Python3.6及以后的版本,推荐使用f-string进行字符串格式化。

采用{content:format}设置字符串格式

https://blog.csdn.net/sunxb10/article/details/81036693

例:f"{a:3.2f}",与printf的格式化输出相似,3指定宽度,2指定精度,f表示浮点数

list

[start : stop : step]

>>> a = [1, 2, 3, 4, 5, 6]
>>> a[::-1]  # 逆序
[6, 5, 4, 3, 2, 1]
>>> a[::2]
[1, 3, 5]
>>> a[0:3:1]
[1, 2, 3]
>>> a[0:3:-1]
[]
>>> a[3:0:1]
[]
>>> a[3:0:-1]
[4, 3, 2]

dict

获取元素

a = dict()
a.items()  # 以(key, value)对的形式,返回字典a的内容
a.keys()
a.values()

删除元素

a = dict.fromkeys('abcd')  # {'a': None, 'b': None, 'c': None, 'd': None}
a.pop(key[, default])  # 返回value,如key不存在,返回default,如未指定default,报错
a.popitem()  # 返回被移除的item: (key, value),一个tuple

python3.7使dict具有了顺序性(几乎可以替代OrderedDict

使得popitem()能够遵循栈的LIFO(last-in, first-out)规则,python3.7之前为随机pop(docs)

查看对象属性

vars(object)等价于object.__dict__,返回一个字典对象,包含对象的属性和值

对于模块(module):

module.__dict__会包含模块的魔法成员(双下划线变量,如__name__

可以通过遍历__dict__,筛选出非魔法成员:

{key: value for key, value in module.__dict__.items() if not key.startswith('__')}

环境变量

可以在python命令前添加当次生效的环境变量,如:

CUDA_LAUNCH_BLOCKING=1 python main.py

然后可以在代码中调用os.environ['CUDA_LAUNCH_BLOCKING']来获取环境变量

有点神秘,这到底是python的特性还是shell的特性呢?是shell的特性,也可以用该方法运行一个指定环境变量的bash

-u

原因是python缓存机制,虽然stderr和stdout默认都是指向屏幕的,但是stderr是无缓存的,程序往stderr输出一个字符,就会在屏幕上显示一个;而stdout是有缓存的,只有遇到换行或者积累到一定的大小,才会显示出来。这就是为什么上面的会最先显示两个stderr的原因。

参考

实例代码:

import sys
sys.stdout.write("stdout1")
sys.stderr.write("stderr1")
sys.stdout.write("stdout2")
sys.stderr.write("stderr2")

contextlib.redirect_stdout

重定向标准输出上下文管理器(用于临时重定向,便于限制有效范围)

python3文档

python3.4加入的新特性(就这百度就搜不到了。。)

New in version 3.4.

例:

with open('a.txt', 'w') as f:
    with redirect_stdout(f):
        print('hello')

http服务器

在当前目录创建http服务器,如果存在index.html文件,则默认为主页(参考):

python3 -m http.server 8888

all() & any()

built-in函数

all(iterable):若iterable中每个元素都为True,则返回True

any(iterable):若iterable中存在为True的元素,则返回True

  all any
All Truthy values True True
All Falsy values False False
One Truthy value(all others are Falsy) False True
One Falsy value(all others are Truthy) False True
Empty True False

一些数组类对象也绑定了all()any()方法,如:(a==b).all()用于判断两个数组是否完全相同(每个元素都相同)

__str__和__repr__

__str__定义print语句的打印格式

__repr__定义python交互模式中对象的显示,以及一些编辑器的变量显示

>>> print(a)
a.__str__
>>> a
a.__repr__

filter, map

用指定的函数,来处理list,以迭代器(生成器)的形式返回结果

好像只有在访问结果的时候才会去计算。也就是说如果参数不匹配也会到实际访问的时候才报错。

filter

filter(function, iterable),python内置函数

function必须接收1个参数(单目运算)

function返回True来筛选iterable里的元素

>>> list(filter(lambda x: x % 2, [1, 2, 3, 4]))
[1, 3]

map

map(function, iterable, ...),python内置函数

function接收的参数个数与传入的iterable的个数一致

对多个iterable做元素级运算:相应元素送入function

>>> list(map(lambda a, b, c: a * b * c, [1, 2, 3], [2, 2, 2], [1, 2, 3]))
[2, 8, 18]

reduce

functools.reduce(function, iterable[, initializer])

iterable缩减为1个值:$return=x_1 \odot x_2 … \odot x_n$,$\odot$表示二元运算function(必须接收2个参数)

>>> from functools import reduce
>>> import operator
>>> reduce(operator.mul, [2, 3, 4])
24

更多参见文档