Anaconda安装踩过的坑:
python中安装yaml时,应该安装pyyaml:conda install pyyaml
创建新环境:conda create -n name python=3.6.3
安装失败,提示channel不符合。
解决:
输入命令: conda update conda ”。
然后输入以下命令:conda create -n py363 python=3.6.3 anaconda ”。
成功,随后可以activate py363。
======================================
陷阱1:一边遍历,一边删除列表元素
可能出现问题:下标超出范围报错,或者返回结果不正确。
陷阱2:b=a,修改a,结果b也被改变了。
陷阱3:input输入一个数字,使用时发现变成了字符串。
如果想使用input()函数输入一个数值,在得到结果后需要用int()将字符串类型转换为数值类型。
陷阱4:在for循环体内改变循环变量的值,结果下次循环依然不被影响。
for i in range(3): print "original:",i i=i+3 print "new",i original: 0 new 3 original: 1 new 4 original: 2 new 5典型的用C语言思想,python并不买账。
陷阱5:remove是删除首个符合条件的元素,而不是根据特定索引。
>>> a=[1,2,3,1] >>> a.remove(a[-1]) >>> a [2, 3, 1] >>>如上代码,本来是想删除最后一个元素,结果误删第一个。
而对于 del 来说,它是根据索引(元素所在位置)来删除的,如下例:
>>> a=[1,2,3,1] >>> del a[0] >>> a [2, 3, 1]
pop是根据索引,返回的是索引指向那个数值。
>>> a=[1,2,3,1] >>> a.pop(2) 3
陷阱6:python中字典的items()函数返回类型为list
我们知道两个列表可直接相加,两个字典直接相加会报错。
于是想到一种相加方式:a.items()+b.items()。但是错误地得到了一个列表。
>>> a={1:2} >>> b={3:4} >>> a+b Traceback (most recent call last): File "<pyshell#123>", line 1, in <module> a+b TypeError: unsupported operand type(s) for +: 'dict' and 'dict' >>> c=a.items()+b.items() >>> c [(1, 2), (3, 4)] >>> type(c) <type 'list'>正确使用方式:update()
>>> a {1: 2} >>> b {3: 4} >>> a.update(b) >>> a {1: 2, 3: 4}
陷阱7:元组或者列表加括号等于自身
>>> a=(1,2) >>> (a) (1, 2) >>> b=[1,2] >>> (b) [1, 2] >>> tuple(a) (1, 2) >>> tuple(b) (1, 2) >>> tuple([a]) ((1, 2),)这告诉我们如果需要使用元祖,最好用tuple()函数转换,而不是加括号强制转化。
陷阱8:迭代器无法改变列表内容
>>> a=["1\t4","a\tb"] >>> for item in a: item = item.split("\t") >>> a ['1\t4', 'a\tb'] >>> for i in range(len(a)): a[i]=a[i].split("\t") >>> a [['1', '4'], ['a', 'b']]
陷阱9:列表解析
列表解析总共有两种形式,很容易把二者混淆:
1. [i for i in range(k) if condition]:此时if起条件判断作用,满足条件的,将被返回成为最终生成的列表的一员。
2. [i if condition else exp for exp]:此时if...else被用来赋值,满足条件的i以及else被用来生成最终的列表。
以上情况对多个for仍然成立。
print([i for i in range(10) if i%2 == 0]) print([i if i == 0 else 100 for i in range(10)]) [0, 2, 4, 6, 8] [0, 100, 100, 100, 100, 100, 100, 100, 100, 100]
陷阱10:矩阵转变为数组,再求和
>>> a=np.mat([[1,2,3],[4,5,6]]) >>> a matrix([[1, 2, 3], [4, 5, 6]]) >>> sum(a) matrix([[5, 7, 9]]) >>> b=[[1,2,3],[4,5,6]] >>> sum(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'list' >>> np.array(a) array([[1, 2, 3], [4, 5, 6]]) >>> np.array(sum(a)) array([[5, 7, 9]]) >>> np.array(sum(a))[0] array([5, 7, 9]) >>> np.array(sum(a)[0]) array([[5, 7, 9]])
陷阱11:float精度损失、round假四舍五入
>>> b=max(np.linalg.eigvals(a)) >>> b 5.3722813232690143 >>> round(b,3) 5.3719999999999999 >>> round(b,2) 5.3700000000000001可以看到两个问题:一室无限循环;二是精度损失;
建议不要用round(),因为它不是严格意义上的四舍五入,而是遇到5舍入时接近一个偶数;
建议用格式化表示:
>>> c = "%.4f" % b >>> c '5.3723' >>> float(c) 5.3723
陷阱12:对象赋值,实际传递了引用
定义类:
import numpy as np class ModelParams(object): def __init__(self): self.beta = 0.8*np.ones(NUMBER_OF_NODES)
定义对象p,并赋值给p1:
p = NodeParams() print(">>>>test<<<<") print(p.beta) p1 = p p1.beta = -1*np.ones(len(p.beta)) print(p.beta) print(p1.beta)
结果(错误):
>>>>test<<<< [ 0.8 0.8 0.8 0.8 0.8] [-1. -1. -1. -1. -1.] [-1. -1. -1. -1. -1.]
可以看到,对象的赋值只是传递了一个引用,改变被赋值的对象,原对象也会被改变。解决:采用深拷贝进行赋值
from copy import deepcopy p = NodeParams() print(">>>>test<<<<") print(p.beta) p1 = p p1.beta = -1*np.ones(len(p.beta)) print(p.beta) print(p1.beta)
结果(正确):
>>>>test<<<< [ 0.8 0.8 0.8 0.8 0.8] [ 0.8 0.8 0.8 0.8 0.8] [-1. -1. -1. -1. -1.] 123陷阱12:列表相加与numpy数组相加
a=[1,2,3] b=[4,5,6] a+b Out[447]: [1, 2, 3, 4, 5, 6] a=np.array(a) b=np.array(b) a,b Out[450]: (array([1, 2, 3]), array([4, 5, 6])) a+b Out[451]: array([5, 7, 9])
解决:用 numpy.concatenate 拼接多个数组
陷阱13:矩阵相乘与数组相乘
a=[[0,1],[2,3]] c1=np.array(a) c2=np.array([1,2]) c2*c1 Out[119]: array([[0, 2], [2, 6]]) np.mat(c2)*np.mat(c1) Out[120]: matrix([[4, 7]])
陷阱14:格式化打印矩阵与打印数组
打印矩阵(失败):
def print_matriax(M): for i in range(len(M)): print(",".join([str(it) for it in M[i]])) a = np.mat([[1,2],[3,4]]) print_matriax(a)
[[1 2]] [[3 4]]
打印数组(成功):
def print_matriax(M): for i in range(len(M)): print(",".join([str(it) for it in M[i]])) a = np.array([[1,2],[3,4]]) print_matriax(a)
1,2 3,4
打印矩阵最终的解决方案(成功):
def print_matriax(M): M = np.array(M) for i in range(len(M)): print(",".join([str(it) for it in M[i]])) a = np.mat([[1,2],[3,4]]) print_matriax(a)
1,2 3,4
陷阱15:numpy数组减去常数
>>> a=np.ones(10)
>>> a
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
>>> a-10
array([-9., -9., -9., -9., -9., -9., -9., -9., -9., -9.])
以上案例原本是numpy的简化操作,但是实际使用中,误引入一个bug:
原本想用np.array(a)-np.array(b),结果b的计算过程出错,得到一个常数,正常应该报错,但是numpy顺利进行了减法操作,导致这个bug被忽略。
陷阱16:np.concatenate(a,b)
如此操作两个numpy数组会报错,因为缺少一层括号。正确为:np.concatenate((a,b), axis=0)
陷阱17:c=a.append(b)
如此操作两个list数组会报错,因为返回append和extend返回None。正确为c=copy.deepcopy(a); c.append(b);
这里用copy.deepcopy是因为有时c不是一个单独数组,而是一个大数组中的子数组。为了避免随后改变a造成c的误变,用deepcopy保险一点。
陷阱18:numpy数组的子数组
numpy定义的数组,如果元素还是数组,会出现两种情况:(1) 子数组长度一样,为numpy.array类别。(2) 子数组长度不一样,为list类别。
a=np.array([[1,2],[3,4]]) type(a) Out[99]: numpy.ndarray type(a[0]) Out[100]: numpy.ndarray b=np.array([[0, 1, 2, 3, 7, 13],[32, 33, 8, 30],[32, 33, 29, 23]]) type(b) Out[102]: numpy.ndarray type(b[0]) Out[103]: list这会造成很多numpy特有函数失效,如flatten():
a.flatten() Out[111]: array([1, 2, 3, 4]) b.flatten() Out[112]: array([[0, 1, 2, 3, 7, 13], [32, 33, 8, 30], [32, 33, 29, 23]], dtype=object)这里涉及到一个多维数组的概念,可能numpy认为多维数组的概念是列数相等。
回到上面的flatten()失效问题,正确的方式是采用np.hstack()函数,可成功将数组拉平。
np.hstack(b) Out[114]: array([ 0, 1, 2, ..., 33, 29, 23])
陷阱19:numpy数组赋值中的bug
numpy数组,必须是像矩阵一样规整的格式,子数组长度相等。
定义一个二维numpy数组,尝试将其中一个子数组定义为变量,结果将所有元素都赋值为这个变量的值了:
a=np.array([[1,2],[3,4]]) a[0] Out[4]: array([1, 2]) a[0]=999 a Out[6]: array([[999, 999], [3, 4]])
错因:加上了索引之后的标签其实指代的就是具体的存储区。见下面案例,就是指向了整个数组存储区,成功赋值:
a=[[1,2],[3,4]] a Out[12]: [[1, 2], [3, 4]] a=1 a Out[14]: 1
尝试给子数组定义为字符数组,尝试失败,无法给int()对象赋值字符串:
a=np.array([[1,2],[3,4]]) a[0]=['a','b'] Traceback (most recent call last): File "<ipython-input-7-304e9d0d6e26>", line 1, in <module> a[0]=['a','b'] ValueError: invalid literal for int() with base 10: 'a'尝试赋值为同格式子数组,成功:
a[0]=[-1,-2] a Out[9]: array([[-1, -2], [ 3, 4]])
陷阱20.【python3.6.3】 networkx中的G.nodes()返回类型不再是列表
for i in range(len(G.nodes)):
print(G.nodes[i])
报错: keyerror: 0
原因:
G.nodes()返回类型是<class 'networkx.classes.reportviews.NodeView'>,这是一个迭代器。其中每个元素都是一个字典。完整代码见:
G = nx.random_graphs.random_regular_graph(2,20) G.nodes() Out[43]: NodeView((17, 18, 7, 14, 10, 11, 8, 13, 9, 15, 4, 5, 19, 3, 1, 0, 6, 16, 12, 2)) for i in range(len(G.nodes())): print(G.nodes[i]) {} {}
陷阱21.定义函数时,如果有的参数有默认值,把这些参数放在没有默认值的参数前会报错
SyntaxError: non-default argument follows default argument
陷阱22. 注意区分networkx中的函数add_node与add_nodes_from
案例(python3.6.3):
G.add_node(12,13):TypeError: add_node() takes 2 positional arguments but 3 were given;
G.add_node([12, 13]):TypeError: unhashable type: 'list'
G.add_node((12,13)):成功加入一个编号为(12,13)的节点
G.add_nodes_from([12,13]):成功加入两个编号为12、13的节点
G.add_edge([(1,2),(3,4)]):TypeError: add_edge() missing 1 required positional argument: 'v'
G.add_edges_from([(1,2),(3,4)]):成功加入边
陷阱23. Error with matplotlib.show() : module 'matplotlib' has no attribute 'show' [duplicate]
不要用:import matplotlib as plt,
改用:import matplotlib.pyplot as plt
陷阱24:外部global定义的全局变量,在函数内赋值;
当你这样做的时候,实际上是在函数内重新定义了一个局部变量。
要想对这个全局变量成功赋值,需要重新在这个函数内部进行global的声明;
陷阱25:在子进程内修改变量,而没有返回结果。
python在函数内部修改对象(结构体、数组)时,是直接改变了这个对象,无返回值也可以。
但是,在多进程中,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,这是多线程和多进程最大的不同。所以如果子进程无返回值,就失去了与主进程的交互,所做修改只是局部有效。