There should be one—and preferably only one—obvious way to do it.
应该提供一种——且最好只提供一种——明显的解决方案。
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
每个数据科学项目都要依赖一些外部库,不同的项目可能需要不同版本的库。为了解决不同项目之间的库版本冲突问题,可以使用虚拟环境(Virtual Environment)。每一个虚拟环境相当于一个沙盒,它们各自维护各自的Python版本和库版本。
一条铁律:在虚拟环境中工作,而不是使用“base”环境。
$ conda info -e # 查看目前所有的虚拟环境
# conda environments:
#
base * /Users/zhuyuxi/opt/anaconda3
dsfs /Users/zhuyuxi/opt/anaconda3/envs/dsfs
$ conda create -n dsfs2 python=3.9 # 创建一个(名为dsfs2的, Python版本号为3.9的)新的虚拟环境
$ conda activate dsfs2 # 激活虚拟环境dsfs2
(base) zhuyuxi@zhuyuxideMacBook-Pro ~ % conda activate dsfs2
(dsfs2) zhuyuxi@zhuyuxideMacBook-Pro ~ %
$ conda deactivate
(dsfs2) zhuyuxi@zhuyuxideMacBook-Pro ~ % conda deactivate
(base) zhuyuxi@zhuyuxideMacBook-Pro ~ %
$ conda remove -n dsfs2 --all # 删除名为dsfs2的虚拟环境
$ conda list
(dsfs) zhuyuxi@zhuyuxideMacBook-Pro ~ % conda list
# packages in environment at /Users/zhuyuxi/opt/anaconda3/envs/dsfs:
#
# Name Version Build Channel
ca-certificates 2022.4.26 hecd8cb5_0
certifi 2021.5.30 py36hecd8cb5_0
libcxx 12.0.0 h2f01273_0
... ... ...
许多语言使用大括号来分隔代码块,但是在Python中使用缩进:
for i in [1, 2, 3, 4, 5]:
print(i) # first line in "for i" block
for j in [1, 2, 3, 4, 5]:
print(j) # first line in "for j" block
print(i + j) # last line in "for j" block
print(i) # last line in "for i" block
print("done looping")
Python会忽略方括号和圆括号内的空格:1. 这对冗长的计算很有帮助 2. 使代码更易读
# Example1
long_winded_computation = (
1 + 2 + 3 + 4 + 5
+ 6 + 7 + 8 + 9 + 10
+ 11 + 12 + 13 + 14 + 15
+ 16 + 17 + 18 + 19 + 20
)
# Example2
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
easier_to_read_list_of_lists = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
注意:使用反斜杠\
也可以使语句继续到下一行,但是这样会降低可读性,因此一般不这么写。
%paste
进行代码的复制粘贴含有whitespace的代码在复制粘贴到Python Shell中执行时总是会出问题,使用Ipython中的%paste
魔法函数可以正确地复制粘贴代码。
复制下面的代码:
for i in [1,2,3,4,5]:
# 注意这里的空行
print(i)
在Ipython中通过%paste
魔法函数粘贴并执行(在In []
后输入%paste
然后按回车键):
In [ ]: %paste
for i in [1,2,3,4,5]:
# 注意这里的空行
print(i)
## -- End pasted text --
1
2
3
4
5
import re # 导入模块本身(不使用别名)
my_regex = re.compile("[0-9]+", re.I) # 通过 re. 访问模块内部的对象
import re as regex # 导入模块本身(使用别名)
my_regex = regex.compile("[0-9]+", regex.I) # 通过 regex. 访问模块内部的对象
from re import compile # 导入re模块中的compile函数对象
my_regex = compile("[0-9]+", re.I) # 直接调用compile函数
from re import *
可以将模块中的内容全部导入命名空间,但是之前代码中的重名对象会直接被覆盖,所以最好不要这么做!通过def关键字定义函数:
def double(x):
"""
在这里,可以使用文档字符串来注释函数的用法。
比如,这个函数就是将输入乘以2。
"""
return x*2 # 如果没有返回值写 return None 或不写
def my_print(msg = "default msg"):
print(msg)
my_print() # 不指定->使用默认参数值,打印 "default msg"
my_print("hello") # 使用指定参数,打印 "hello"
my_print(msg="hello") # 按参数名称指定参数值
在Python中函数也是一种对象:
my_double = double # my_double是函数double的别名
a = 10
a_doubled = my_double(a) # 可以通过函数的别名来调用函数,等价于直接调用函数
# 等价于:a_doubled = double(a)
def apply_to_one(func):
"""
将1作为参数调用函数func
"""
return func(1)
one_doubled = apply_to_one(double) # one_doubled = 2
lambda函数是匿名函数,语法格式为:lambda
,其中:
lambda
是Python中的预留关键字
是参数列表,使用方法与函数的参数列表相同
是一个关于参数的表达式,表达式中出现的参数需要在
中有定义,并且表达式只能是单行的,该表达式的计算结果即为该lambda函数的输出y = apply_to_one(lambda x:x+4) # y is 5
# Equals to
def add_four(x):
return x + 4
y = apply_to_one(add_four) # y is 5
注意:也可以将lambda函数赋给变量,这相当于给它了一个名字;但是最好不要这么写,如果你真的想创建一个具名函数就直接用def
去定义就好了。
another_double = lambda x: 2*x # 不好的写法
def another_double(x):
"""好的写法"""
return 2*x
single_quoted_string = 'data science'
double_quoted_string = "data science"
tab_string = "\t" # 表示单个Tab字符组成的字符串
len(tab_string) # 单个Tab字符 -> len为1
r"..."
not_tab_string = r"\t" # 表示字符'\'和't'组成的字符串
len(not_tab_string) # 2
multi_line_string = """The first line.
The second line.
The third line."""
first_name = "Joel"
second_name = "Grus"
# 组合full-name的三种方式
full_name_concat = first_name + " " + second_name
full_name_format = "{0} {1}".format(first_name, second_name)
full_name_fstring = f"{first_name} {second_name}" # (推荐)更简洁明了
try:
print(0/0)
except ZeroDivisionError:
print("cannot divide by zero")
cannot divide by zero
虽然在许多语言中异常被认为是不好的情况,但是在Python中,不必因为使用这些技巧而感到难堪,有时这么做可以让代码更清晰。