少儿学习Python编程必须要杜绝的3个错误

少儿学习Python编程必须要杜绝的3个错误
少儿学习Python编程必须要杜绝的3个错误

少儿学习Python编程

必须要杜绝的3个错误

2017.11.19

承认自己的犯错永远不是一件简单的事情,然而人们往往得从犯错中学习知识,无论是学习不行乃至学习编程,我们就以Python为例。

下面是我在学习Python时犯过的3个错误,写下来给新学习Python的朋友们,避免和我一样犯下同样的错误。这些错误包括了我侥幸避免的以及花了长时间才修复的问题。接下来就让我们来看看是哪几个错误。

1.在函数定义中,将可变数据类型作为默认参数

现在让我们来看一下这个简单的函数,我们将从当前页面抓取连接并将其添加到另一个列表中。

def search_for_links(page,add_to=[]):

new_links =page.search_for_links()

add_to.extend(new_links)

return add_to

从表面来看,运行的很好,而事实也的确如此,它的确能运行。然而其中却有许多问题,如果我们用add_to作为参数,它可以如我们所想一样运行。然而如果我们使用默认参数,那么就会发生一些有趣的事情。

以下面的代码为例

def fn(var1,var2=[]):

var2.append(var1)

print var2

fn(3)

fn(4)

fn(5)

你可能以为我们能看到这样的结果

[3]

[4]

[5]

然而事实却是这样的

[3]

[3, 4]

[3, 4, 5]

为什么?你可以看到同样的列表被调用了三次,而在Python中,我们写出那样的函数,列表将实例化并作为函数定义的一部分,而并不是在每次函数运行的时候实例化。这说明了函数将会使用同样的列表内对象一遍又一遍,除非我们将函数修改成这样

fn(3,[4])

[4, 3]

如我们所想的,正确的方式是这样的:

def fn(var1,var2=None):

if not var2:

var2 =[]

var2.append(var1)

或者以我们第一个例子为例:

def search_for_links(page,add_to=None):

if not add_to:

add_to =[]

new_links =page.search_for_links()

add_to.extend(new_links)

return add_to

这一步将实例化从模块读取的时间中移出,这样实例化才能在每次函数运行的时候同步发生。而对于不可变数据类型则没有必要,只要做以下两步即可

2.将可变数据类型作为变量

紧随其后的错误就很普遍了,让我们来看一下:

class URLCatcher(object):

urls =[]

def add_url(self,url):

self.urls.append(url)

代码看起来没有任何问题是不是?这段代码将调用add_url来把连接储存到urls列表里去,那么接下来让我们来看下一步

a =URLCatcher()

a.add_url('http://www.google.')

b =URLCatcher()

b.add_url('http://www.bb

c.co.')

b.urls

['https://www.360docs.net/doc/a39022928.html,', 'https://www.360docs.net/doc/a39022928.html,']

a.urls

['https://www.360docs.net/doc/a39022928.html,', 'https://www.360docs.net/doc/a39022928.html,']

等等!为什么两个列表都有2个链接?我们不是分别将他储存进不同的列表了吗?

看起来其实和之前的问题有一点像,同样是将url列表编入了类的定义里,所以为了避免这种情况,我们可以通过这种方式来分别储存。

class URLCatcher(object):

def__init__(self):

self.urls=[]

def add_url(self,url):

self.urls.append(url)

现在我们就可以将两个链接分别储存了。

3.用可变数据类型来赋值

这个问题困扰我许久,现在让我们看一下如果使用字典会产生什么问题吧。

a ={'1': "one",'2': 'two'}

现在假设我们要将字典用在其他地方并且保留原字典内容

b = a

b['3']='three'

是不是很简单?

那么回过头来再让我们看一下字典a里的内容

{'1': "one",'2': 'two','3': 'three'}

现在字典a和字典b完全一样了,而如果我们用不可变数据类型来做结果就完全不同,以元组为例:

c =(2,3)

d = c

d =(4,5)

现在c是:

(2, 3)

元组d是:

(4, 5)

这次就成功地达到了我们的目的。那么为什么在例子中我们会失败?因为对于Python 来说,当我们输入b=a,那么a与b之间会形成一个相互引用的关系,这其实就和我们之前的2个问题非常相似,这也是所有可变数据类型最可能造成的麻烦。

如果我们真的很需要将部分列表调用出来来处理的话,那么我们可以用以下方法来做:b =a[:]

通过这行代码,我们可以得到一个崭新的列表,但是如果在列表中的对象是可变数据类型而不是单纯的数据,那么同样会造成相同的问题。

正如A和B同时看着一份列表,而通过这行代码,A和B可以拥有各自的列表,然而如果列表中含有可变的数据类型,那么当A修改这个对象时,B同样会看到数据的改变。

字典也可以通过这行代码来实现这个目的。

b = a.copy()

同样的,如果按照刚刚的问题来修改的话,也会得到相同的结果。可变数据类型的麻烦的确很大,所以我们在平时编程时更要注重细节,避免类似错误的发生。

相关主题
相关文档
最新文档