安装
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 参数解析器
-
位置参数 positional arguments
根据参数的位置顺序来进行赋值,缺点是参数多了容易忘记顺序,好处是简单、简洁,适合参数少的情况
默认情况下必须给一个值,缺点是如果需要指定位置靠后的参数就必须同时指定前面的参数
nargs='?'
表示如果可能的话,从命令行消耗一个参数(表示可有可无),配合default=...
可以给位置参数指定默认值 -
可选参数/选项 optional arguments
通常全称用
--foo
,简称用-f
通过定义的参数名字来传参
--foo=123
,而不是位置,适合参数多的情况要让一个选项成为必需的,则可以将
True
作为required=
关键字参数传给 add_argument() -
可以直接调用
parse_args
来给参数赋值:parser.parse_args(['--foo', '2'])
下划线
前导单下划线
定义私有成员。这是一种约定,没有强制性,理论上还是可以从外部访问,只是约定不应该从外部访问_
开头的名字
用通配符*从模块中导入所有名称默认不会导入带有前导单下划线的名称
因此,尽量避免使用通配符导入
前导双下划线
名称转写:双下划线开头,结尾最多一个下划线的名字__a_
,会被自动转换成_类名__a_
后缀单下划线
通常用于与关键字做区分,当有变量名与python关键字相同时,可以添加后缀单下划线(slice_)进行区分
None
判断list中的无效(None)元素:
if x[i] is not None:
pass
函数参数
参数分类
- 对于形参(声明函数),可分为
- 普通参数:既不是默认值参数,也不是可变参数;消耗一个位置或关键字参数
- 可选参数optional:带默认值,必须位于普通参数后面;消耗一个位置或关键字参数
- 可变参数:本质是一个容器(tuple, dict),包含任意多个参数;消耗所有未匹配的参数
- 对于实参(调用函数),可分为:
- 位置参数:
function(value1, value2, ...)
- 关键字参数:
function(keyword1=value1, keyword2=value2, ...)
- 位置参数:
*和**
-
声明函数时,写在形参前,表明该参数为可变参数,如
*args
和**kwargs
-
args
是一个元组(tuple),收集实参中所有未匹配的位置参数 -
kwargs
是一个字典(dict),收集实参中所有未匹配的关键字参数
参数名
args
和kwargs
只是约定成俗的缺省名,可改用其他可读性更高的名字 -
-
调用函数时,写在实参前,用于解包,将容器(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
的文件夹被称为包
语法
-
import ...
只能导入模块import [module]
-
from ... import ...
既可以导入模块也模块中的方法from [module] import [function]
包/模块的概念
利用
__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}
设置字符串格式
例: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()
-
返回值说明
以上3个函数返回的是Dictionary view objects(视图对象),是一种dynamic view(动态视图)
view objects可迭代,但无法按索引(随机)访问
dynamic体现在:如果原本的dict更新,view objects也会自动更新
python2中,返回的是list,即可迭代也可随机访问
-
实际应用
可用于for循环迭代;直接迭代
a
的话,只能得到key如果需要按索引访问,可以先转换成
list( a.keys() )
删除元素
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.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交互模式中对象的显示,以及一些编辑器的变量显示
- 如果只定义了
__repr__
没有定义__str__
,则print
也会打印__str__
的内容
>>> 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
更多参见文档