【Python有坑系列大合集】

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。

关于错误:ImportError: No module named yaml,注意:

pip install pyyaml lets you import yaml. This package enables Python to parse YAML files.
pip install pyaml lets you import pyaml. This package allows pretty-printing of YAML files 

======================================

坑1:一边遍历,一边删除列表元素

可能出现问题:下标超出范围报错,或者返回结果不正确。

<pre class="has">
<code class="language-python">a=[1,2,3,4,5,6,7]
b=[1,6]
for it in a:
if it not in b:
print("remove ",it)
print(a)
a.remove(it)
print(a)
remove 2
[1,7]
[1,7]
remove 4
[1,7]
remove 7
[1,6]

坑2:b=a,修改a,结果b也被改变了。

坑3:input输入一个数字,使用时发现变成了字符串。

如果想使用input()函数输入一个数值,在得到结果后需要用int()将字符串类型转换为数值类型

坑4:在for循环体内改变循环变量的值,结果下次循环依然不被影响。

<pre class="has">
<code class="language-python">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并不买账。

删除首个符合条件的元素,而不是根据特定索引。

<pre class="has">
<code class="language-python">>>> a=[1,1]

a.remove(a[-1])
a
[2,1]

如上代码,本来是想删除最后一个元素,结果误删第一个

而对于 del 来说,它是根据索引(元素所在位置)来删除的,如下例:

<pre class="has">
<code class="language-python">>>> a=[1,1]

del a[0]
a
[2,1]

pop是根据索引,返回的是索引指向那个数值。

<pre class="has">
<code class="language-python">>>> a=[1,1]

a.pop(2)
3

坑6:python中字典的items()函数返回类型为list

我们知道两个列表可直接相加,两个字典直接相加会报错。

于是想到一种相加方式:a.items()+b.items()。但是错误地得到了一个列表。

<pre class="has">
<code class="language-python">>>> a={1:2}

b={3:4}
a+b
Traceback (most recent call last):
File "<pyshell#123>",line 1,in
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'>

<pre class="has">
<code class="language-html">正确使用方式:update()

<pre class="has">
<code class="language-python">>>> a
{1: 2}

b
{3: 4}
a.update(b)
a
{1: 2,3: 4}

元组或者列表加括号等于自身

<pre class="has">
<code class="language-python">>>> a=(1,2)

(a)
(1,2)
b=[1,2]
(b)
[1,2]
tuple(a)
(1,2)
tuple(b)
(1,2)
tuple([a])
((1,)

这告诉我们如果需要使用元祖,最好用tuple()函数转换,而不是加括号强制转化。

内容

<pre class="has">
<code class="language-python">>>> 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']]

列表解析

列表解析总共有两种形式,很容易把二者混淆:

1. [i for i in range(k) if condition]:此时if起条件判断作用,满足条件的,将被返回成为最终生成的列表的一员。

2. [i if condition else exp for exp]:此时if...else被用来赋值,满足条件的i以及else被用来生成最终的列表。

以上情况对多个for仍然成立。

<pre class="has">
<code class="language-python">print([i for i in range(10) if i%2 == 0])
print([i if i == 0 else 100 for i in range(10)])

[0,8]
[0,100,100]

坑10:矩阵转变为数组,再求和

<pre class="has">
<code class="language-python">>>> a=np.mat([[1,3],[4,6]])

a
matrix([[1,6]])
sum(a)
matrix([[5,7,9]])
b=[[1,6]]
sum(b)
Traceback (most recent call last):
File "",in
TypeError: unsupported operand type(s) for +: 'int' and 'list'
np.array(a)
array([[1,6]])
np.array(sum(a))
array([[5,9]])
np.array(sum(a))[0]
array([5,9])
np.array(sum(a)[0])
array([[5,9]])

坑11:float精度损失、round假四舍五入

<pre class="has">
<code class="language-python">>>> b=max(np.linalg.eigvals(a))

b
5.3722813232690143
round(b,3)
5.3719999999999999
round(b,2)
5.3700000000000001

可以看到两个问题:一室无限循环;二是精度损失;

建议不要用round(),因为它不是严格意义上的四舍五入,而是遇到5舍入时接近一个偶数;

建议用格式化表示:

<pre class="has">
<code class="language-python">>>> c = "%.4f" % b

c
'5.3723'
float(c)
5.3723

坑12:对象赋值,实际传递了引用

定义类:

<pre class="has">
<code class="language-python">import numpy as np
class ModelParams(object):
def init(self):
self.beta = 0.8*np.ones(NUMBER_OF_NODES)

定义对象p,并赋值给p1:

<pre class="has">
<code class="language-python">p = NodeParams()
print(">>>>test<<<<")
print(p.beta)
p1 = p
p1.beta = -1*np.ones(len(p.beta))
print(p.beta)
print(p1.beta)

结果(错误):

<pre class="has">
<code class="language-python">>>>>test<<<<
[ 0.8 0.8 0.8 0.8 0.8]
[-1. -1. -1. -1. -1.]
[-1. -1. -1. -1. -1.]

可以看到,对象的赋值只是传递了一个引用,改变被赋值的对象,原对象也会被改变。解决:采用深拷贝进行赋值

<pre class="has">
<code class="language-python">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)

结果(正确):

<pre class="has">
<code class="language-python">>>>>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数组相加

<pre class="has">
<code class="language-python">a=[1,3]

b=[4,6]

a+b
Out[447]: [1,6]

a=np.array(a)

b=np.array(b)

a,b
Out[450]: (array([1,3]),array([4,6]))

a+b
Out[451]: array([5,9])

解决:用 numpy.concatenate 拼接多个数组

坑13:矩阵相乘与数组相乘

<pre class="has">
<code class="language-python">a=[[0,1],[2,3]]
c1=np.array(a)
c2=np.array([1,2])
c2*c1
Out[119]:
array([[0,2],6]])

np.mat(c2)*np.mat(c1)
Out[120]: matrix([[4,7]])

坑14:格式化打印矩阵与打印数组

打印矩阵(失败):

<pre class="has">
<code class="language-python">def print_matriax(M):
for i in range(len(M)):
print(",".join([str(it) for it in M[i]]))
a = np.mat([[1,[3,4]])
print_matriax(a)

<pre class="has">
<code class="language-python">[[1 2]]
[[3 4]]

打印数组(成功):

<pre class="has">
<code class="language-python">def print_matriax(M):
for i in range(len(M)):
print(",".join([str(it) for it in M[i]]))
a = np.array([[1,4]])
print_matriax(a)

<pre class="has">
<code class="language-python">1,2
3,4

打印矩阵最终的解决方案(成功):

<pre class="has">
<code class="language-python">def print_matriax(M):
M = np.array(M)
for i in range(len(M)):
print(",4

坑15:numpy数组减去常数

<pre class="has">
<code class="language-python">>>> a=np.ones(10)

a
array([ 1.,1.,1.])
a-10
array([-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类别。

<pre class="has">
<code class="language-python">a=np.array([[1,4]])

type(a)
Out[99]: numpy.ndarray

type(a[0])
Out[100]: numpy.ndarray

b=np.array([[0,1,13],[32,33,8,30],29,23]])

type(b)
Out[102]: numpy.ndarray

type(b[0])
Out[103]: list

这会造成很多numpy特有函数失效,如flatten():

<pre class="has">
<code class="language-python">a.flatten()
Out[111]: array([1,4])

b.flatten()
Out[112]: array([[0,23]],dtype=object)

这里涉及到一个多维数组的概念,可能numpy认为多维数组的概念是列数相等。

回到上面的flatten()失效问题,正确的方式是采用np.hstack()函数,可成功将数组拉平。

<pre class="has">
<code class="language-python">np.hstack(b)
Out[114]: array([ 0,...,23])

numpy数组,必须是像矩阵一样规整的格式,子数组长度相等。

定义一个二维numpy数组,尝试将其中一个子数组定义为变量,结果将所有元素都赋值为这个变量的值了:

<pre class="has">
<code class="language-python">a=np.array([[1,4]])

a[0]
Out[4]: array([1,2])

a[0]=999

a
Out[6]:
array([[999,999],4]])

错因:加上了索引之后的标签其实指代的就是具体的存储区。见下面案例,就是指向了整个数组存储区,成功赋值:

<pre class="has">
<code class="language-python">a=[[1,4]]

a
Out[12]: [[1,4]]

a=1

a
Out[14]: 1

尝试给子数组定义为字符数组,尝试失败,无法给int()对象赋值字符串:

<pre class="has">
<code class="language-python">a=np.array([[1,4]])
a[0]=['a','b']
Traceback (most recent call last):

File "",in
a[0]=['a','b']

ValueError: invalid literal for int() with base 10: 'a'

尝试赋值为同格式子数组,成功:

<pre class="has">
<code class="language-python">a[0]=[-1,-2]

a
Out[9]:
array([[-1,-2],[ 3,4]])

python3.6.3】 networkx中的G.nodes()返回类型不再是列表

for i in range(len(G.nodes)):

    print(G.nodes[i])

报错: keyerror: 0

原因:

G.nodes()返回类型是,这是一个迭代器。其中每个元素都是一个字典。完整代码见:

<pre class="has">
<code class="language-python">G = nx.random_graphs.random_regular_graph(2,20)

G.nodes()
Out[43]: NodeView((17,18,14,10,11,13,9,15,19,16,12,2))

for i in range(len(G.nodes())):
print(G.nodes[i])

{}
{}

函数时,如果有的参数有认值,把这些参数放在没有认值的参数前会报错

SyntaxError: non-default argument follows default argument

函数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,4)]):TypeError: add_edge() missing 1 required positional argument: 'v'

G.add_edges_from([(1,4)]):成功加入边

不要用:import matplotlib as plt

改用:import matplotlib.pyplot as plt

坑24:外部global定义的全局变量,在函数内赋值;

函数内重新定义了一个局部变量。

全局变量成功赋值,需要重新在这函数内部进行global的声明;

修改变量,而没有返回结果。

函数内部修改对象(结构体、数组)时,是直接改变了这个对象,无返回值也可以。

一个变量,各自有一份拷贝存在于每个进程中,这是修改只是局部有效。

36:用lambda给字典赋值

lambda表达式中变量的作用域
>>> d = dict()
# 这里有个坑
>>> for i in range(5):
       d[i] = lambda :i**2
 
>>> d[2]()
16
>>> d[3]()
16
# 这样看的更清楚一些
# lambda表达式中i的值是调用时决定的
>>> i = 10
>>> d[0]()
100
# 写成下面这样子就没问题了
>>> d = dict()
>>> for i in range(5):
       d[i] = lambda x=i:x**2
 
>>> d[2]()
4
>>> d[3]()
9

函数也是对象,认参数在首次调用的时候初始化,有坑。

调用时,如果认参数没有被赋值,它指向第一次传入的值。

引用一个官方的经典示例diomatic/handout.html#default-parameter-values" rel="nofollow">地址 :

<pre class="has">
def bad_append(new_item,a_list=[]):
a_list.append(new_item)
return a_list

print(bad_append('1'))
print(bad_append('2'))

这个示例并没有按照预期打印:

<pre class="has">
['1']
['2']

而是打印了:

<pre class="has">
['1']
['1','2']

其实这个错误问题不在认参数上,而是我们对于及认参数的初始化的理解有误。

Python哲学:

一切皆对象

函数也是一个对象,如下示例:

<pre class="has">
import types

def test():
pass

print(type(test)) # <class 'function'>
print(isinstance(test,types.FunctionType)) # True

如此,函数就是类types.FunctionType或者其子类的实例对象。那么对象必然有其初始化的时候,一般来说,解释器在读到函数末尾时完成函数实例的初始化。初始化后,就有了函数名到函数对象这样一个映射关系,可以通过函数名访问到函数对象了,并且,函数的一切属性也确定下来,包括所需的参数,认参数的值。因此每次调用函数时,认参数值是相同的(如果有认参数)。

最佳实践

不可变的认参数的多次调用不会造成任何影响,可变认参数的多次调用的结果不符合预期。那么在使用可变认参数时,就不能只在函数定义时初始化一次,而应该在每次调用时初始化。

最佳实践是定义函数时指定可变认参数的值为None,在函数体内部重新绑定认参数的值。以下是对上面的两个可变认参数示例最佳实践的应用:

<pre class="has">
def good_append(new_item,a_list = None):

if a_list is None:
    a_list = []

a_list.append(new_item)
return a_list

print(good_append('1'))
print(good_append('2'))
print(good_append('c','b']))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我最近重新拾起了计算机视觉,借助Python的opencv还有face_recognition库写了个简单的图像识别demo,额外定制了一些内容,原本想打包成exe然后发给朋友,不过在这当中遇到了许多小问题,都解决了,记录一下踩过的坑。 1、Pyinstaller打包过程当中出现warning,跟d
说到Pooling,相信学习过CNN的朋友们都不会感到陌生。Pooling在中文当中的意思是“池化”,在神经网络当中非常常见,通常用的比较多的一种是Max Pooling,具体操作如下图: 结合图像理解,相信你也会大概明白其中的本意。不过Pooling并不是只可以选取2x2的窗口大小,即便是3x3,
记得大一学Python的时候,有一个题目是判断一个数是否是复数。当时觉得比较复杂不好写,就琢磨了一个偷懒的好办法,用异常处理的手段便可以大大程度帮助你简短代码(偷懒)。以下是判断整数和复数的两段小代码: 相信看到这里,你也有所顿悟,能拓展出更多有意思的方法~
文章目录 3 直方图Histogramplot1. 基本直方图的绘制 Basic histogram2. 数据分布与密度信息显示 Control rug and density on seaborn histogram3. 带箱形图的直方图 Histogram with a boxplot on t
文章目录 5 小提琴图Violinplot1. 基础小提琴图绘制 Basic violinplot2. 小提琴图样式自定义 Custom seaborn violinplot3. 小提琴图颜色自定义 Control color of seaborn violinplot4. 分组小提琴图 Group
文章目录 4 核密度图Densityplot1. 基础核密度图绘制 Basic density plot2. 核密度图的区间控制 Control bandwidth of density plot3. 多个变量的核密度图绘制 Density plot of several variables4. 边
首先 import tensorflow as tf tf.argmax(tenso,n)函数会返回tensor中参数指定的维度中的最大值的索引或者向量。当tensor为矩阵返回向量,tensor为向量返回索引号。其中n表示具体参数的维度。 以实际例子为说明: import tensorflow a
seaborn学习笔记章节 seaborn是一个基于matplotlib的Python数据可视化库。seaborn是matplotlib的高级封装,可以绘制有吸引力且信息丰富的统计图形。相对于matplotlib,seaborn语法更简洁,两者关系类似于numpy和pandas之间的关系,seabo
Python ConfigParser教程显示了如何使用ConfigParser在Python中使用配置文件。 文章目录 1 介绍1.1 Python ConfigParser读取文件1.2 Python ConfigParser中的节1.3 Python ConfigParser从字符串中读取数据
1. 处理Excel 电子表格笔记(第12章)(代码下载) 本文主要介绍openpyxl 的2.5.12版处理excel电子表格,原书是2.1.4 版,OpenPyXL 团队会经常发布新版本。不过不用担心,新版本应该在相当长的时间内向后兼容。如果你有新版本,想看看它提供了什么新功能,可以查看Open
1. 发送电子邮件和短信笔记(第16章)(代码下载) 1.1 发送电子邮件 简单邮件传输协议(SMTP)是用于发送电子邮件的协议。SMTP 规定电子邮件应该如何格式化、加密、在邮件服务器之间传递,以及在你点击发送后,计算机要处理的所有其他细节。。但是,你并不需要知道这些技术细节,因为Python 的
文章目录 12 绘图实例(4) Drawing example(4)1. Scatterplot with varying point sizes and hues(relplot)2. Scatterplot with categorical variables(swarmplot)3. Scat
文章目录 10 绘图实例(2) Drawing example(2)1. Grouped violinplots with split violins(violinplot)2. Annotated heatmaps(heatmap)3. Hexbin plot with marginal dist
文章目录 9 绘图实例(1) Drawing example(1)1. Anscombe’s quartet(lmplot)2. Color palette choices(barplot)3. Different cubehelix palettes(kdeplot)4. Distribution
Python装饰器教程展示了如何在Python中使用装饰器基本功能。 文章目录 1 使用教程1.1 Python装饰器简单示例1.2 带@符号的Python装饰器1.3 用参数修饰函数1.4 Python装饰器修改数据1.5 Python多层装饰器1.6 Python装饰器计时示例 2 参考 1 使
1. 用GUI 自动化控制键盘和鼠标第18章 (代码下载) pyautogui模块可以向Windows、OS X 和Linux 发送虚拟按键和鼠标点击。根据使用的操作系统,在安装pyautogui之前,可能需要安装一些其他模块。 Windows: 不需要安装其他模块。OS X: sudo pip3
文章目录 生成文件目录结构多图合并找出文件夹中相似图像 生成文件目录结构 生成文件夹或文件的目录结构,并保存结果。可选是否滤除目录,特定文件以及可以设定最大查找文件结构深度。效果如下: root:[z:/] |--a.py |--image | |--cat1.jpg | |--cat2.jpg |
文章目录 VENN DIAGRAM(维恩图)1. 具有2个分组的基本的维恩图 Venn diagram with 2 groups2. 具有3个组的基本维恩图 Venn diagram with 3 groups3. 自定义维恩图 Custom Venn diagram4. 精致的维恩图 Elabo
mxnet60分钟入门Gluon教程代码下载,适合做过深度学习的人使用。入门教程地址: https://beta.mxnet.io/guide/getting-started/crash-course/index.html mxnet安装方法:pip install mxnet 1 在mxnet中使
文章目录 1 安装2 快速入门2.1 基本用法2.2 输出图像格式2.3 图像style设置2.4 属性2.5 子图和聚类 3 实例4 如何进一步使用python graphviz Graphviz是一款能够自动排版的流程图绘图软件。python graphviz则是graphviz的python实