【Python有坑系列大合集】

【Python有坑系列大合集】,第1张

概述Anaconda安装踩过的坑:python中安装yaml时,应该安装pyyaml:condainstallpyyaml创建新环境:condacreate-nnamepython=3.6.3

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 

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

<pre >
<code >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]

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

<pre >
<code >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 >
<code >>>> a=[1,1]

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

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

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

<pre >
<code >>>> a=[1,1]

del a[0]
a
[2,1]

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

<pre >
<code >>>> a=[1,1]

a.pop(2)
3

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

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

<pre >
<code >>>> 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 >
<code >正确使用方式:update()

<pre >
<code >>>> a
{1: 2}

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

<pre >
<code >>>> 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 >
<code >>>> 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 >
<code >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]

<pre >
<code >>>> 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]])

<pre >
<code >>>> b=max(np.linalg.eigvals(a))

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

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

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

建议用格式化表示:

<pre >
<code >>>> c = "%.4f" % b

c
'5.3723'
float(c)
5.3723

定义类:

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

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

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

结果(错误):

<pre >
<code >>>>>test<<<<
[ 0.8 0.8 0.8 0.8 0.8]
[-1. -1. -1. -1. -1.]
[-1. -1. -1. -1. -1.]

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

<pre >
<code >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 >
<code >>>>>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

<pre >
<code >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 拼接多个数组

<pre >
<code >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]])

打印矩阵(失败):

<pre >
<code >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 >
<code >[[1 2]]
[[3 4]]

打印数组(成功):

<pre >
<code >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 >
<code >1,2
3,4

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

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

<pre >
<code >>>> 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被忽略。

如此 *** 作两个numpy数组会报错,因为缺少一层括号。正确为:np.concatenate((a,b),axis=0)

如此 *** 作两个List数组会报错,因为返回append和extend返回None。正确为c=copy.deepcopy(a); c.append(b);

这里用copy.deepcopy是因为有时c不是一个单独数组,而是一个大数组中的子数组。为了避免随后改变a造成c的误变,用deepcopy保险一点。

numpy定义的数组,如果元素还是数组,会出现两种情况:(1) 子数组长度一样,为numpy.array类别。(2) 子数组长度不一样,为List类别。

<pre >
<code >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 >
<code >a.flatten()
Out[111]: array([1,4])

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

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

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

<pre >
<code >np.hstack(b)
Out[114]: array([ 0,...,23])

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

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

<pre >
<code >a=np.array([[1,4]])

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

a[0]=999

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

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

<pre >
<code >a=[[1,4]]

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

a=1

a
Out[14]: 1

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

<pre >
<code >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 >
<code >a[0]=[-1,-2]

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

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

    print(G.nodes[i])

报错: keyerror: 0

原因:

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

<pre >
<code >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

案例(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

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

引用一个官方的经典示例href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.HTML#default-parameter-values" rel="nofollow">地址 :

<pre >
def bad_append(newitem,aList=[]):
a_List.append(newitem)
return a
List

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

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

<pre >
['1']
['2']

而是打印了:

<pre >
['1']
['1','2']

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

Python哲学:

一切皆对象

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

<pre >
import types

def test():
pass

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

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

最佳实践

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

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

<pre >
def good_append(newitem,aList = None):

if a_<a href="https://m.jb51.cc/tag/List/" target="_blank" >List</a> is None:    a_<a href="https://m.jb51.cc/tag/List/" target="_blank" >List</a> = []a_<a href="https://m.jb51.cc/tag/List/" target="_blank" >List</a>.append(new_item)return a_<a href="https://m.jb51.cc/tag/List/" target="_blank" >List</a>

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

总结

以上是内存溢出为你收集整理的【Python有坑系列大合集】全部内容,希望文章能够帮你解决【Python有坑系列大合集】所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1209091.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存