这些常见的坑,90%的程序猿都踩过,来看看里面有没有你的脚印?

在学习python的过程中,相信大家都有踩过不少的坑,有些坑可能踩了不止一次,感觉就像是在坑与坑之间反复横跳。那么如何避免这些坑呢?看完这篇文章,你就知道了。我们来谈谈我们学习python的过程中,最常见的七大坑

1. 缩进,符号和空格不正确

写代码时大家会使用缩进、对齐、空格等,这些是为了提高代码的可读性

在python语言中,缩进是十分重要的

比如在创建一个新类时,该类中的所有内容都在声明下缩进,决策、循环还有其它结构语句也会出现类似的情况,

代码执行时如果存在问题,可以先查看一下缩进是否正确。

这边有个例子,在使用IF语句时,请确保使用正确且合适的冒号和缩进,因为它们会导致语法和缩进错误。

val = 500

if val > 100

print(“value is grater then 100”)

File “”, line 2

if val > 100

^

SyntaxError: invalid syntax

在上面的代码当中,出现了两处错误:if语句后面的:缺失;下一行没有进行正确的缩进,执行代码出错。

val = 500

if val > 100:

print(“value is grater then 100”)

value is grater then 100

更正这两个问题之后,代码可以很好的运行

2. 变量使用不正确

class A(object):x = 1

class B(A):pass

class C(A):pass

print( A.x, B.x, C.x)

1 1 1

这里输出的值都是1,然后我们试着来改变一下A.x和B.x的值看看有什么变化。

B.x = 2

print (A.x, B.x, C.x)

A.x = 3

print (A.x, B.x, C.x)

1 2 1

3 2 3

我们只改变了A.x,为什么C.x改变呢?

这里需要了解到python的命名空间。

python中,命名空间是名字到对象映射的结合,不同命名空间中的名字是没有关联的,这种映射的实现有点类似于python中的字典。

当你名字访问一个对象的属性时,先从对象的命名空间寻找。如果找到了这个属性,就返回这个属性的值;如果没有找到的话,则从类的命名空间中寻找,找到了就返回这个属性的值,找不到则抛出异常。

在Python中,类变量在内部作为字典处理,并遵循通常称为方法解析顺序(MRO)的方法。

MRO:Method Resolution Order方法解析顺序,Python支持多继承,该方法用于解决父类存在同名函数的时存在的二义性问题。

因此在上面的代码中,由于x在对象的命名空间中找不到该属性C,因此将在类中查找它。换句话说,C没有自己的x属性,独立于A。因此,引用C.x实际上是指A.x。

3.不了解python范围规则

倘若不知道python的范围规则,那么犯错误的可能性会大大增加,这是因为Python使用一种独有的范围规则来确定变量范围。

python范围解析是基于LEGB规则,以下是Python范围规则的概述:

·L -代表Local。它包含在函数内指定的(标识符/变量)名称(使用def或lambda),而不是使用global关键字声明。

·E -代表Enclosing function locals。它包含来自任何/所有封闭函数的本地范围的名称(例如,使用def或lambda)。

·G -指全球实体。它包括在模块文件的顶层运行或使用global关键字定义的名称。

·B -指内置插件。它跨越预先指定为内置名称的名称,如打印,输入,打开等。

LEGB规则指定名称空间的以下顺序,用于搜索名称:

Local - > Enclosed - > Global - > Built-in

考虑以下的例子:

x = 10

def foo():

x += 1

print(x)

foo()

UnboundLocalError Traceback (most recent call last):

in

in foo()

UnboundLocalError: local variable xreferenced before assignment

发生上述错误的原因是,对作用域中的变量进行赋值时,Python会自动将该变量视为该作用域的本地变量,并在外部作用域中隐藏任何类似命名的变量。

因此,许多人在代码提示出错并显示需要在函数中添加赋值语句而感到不解。

考虑一个在使用列表时遇到的例子:

lst = [1, 2, 3]

def foo1():

lst.append(5)

foo1()

lst

[1, 2, 3, 5]

lst = [1, 2, 3]

def foo2():

lst += [5]

foo2()

UnboundLocalError  Traceback (most recent call last):

in

in foo2()

UnboundLocalError: local variable lstreferenced before assignment

为什么foo2出错了但是foo1运行良好?

答案在前面就已经有所提示,在这个例子当中foo1()做一个分配到lst,而在foo2()当中lst += [5]其实只是lst = lst + [5]的简写,我们希望分配一个值给lst,但是分配的值lst是基于lst自身,但其尚未定义。

4. python闭包变量绑定

python的闭包变量问题也是新手们容易混淆的一个点,来看看下面的例子:

def create_multipliers():

return [lambda x : i * x for i in range(5)]

for multiplier in create_multipliers():

print (multiplier(2))

8

8

8

8

8

为什么结果是88888,和我所想的02468不一样呢?

这是由于Python的迟绑定(late binding)机制,闭包中内部函数的值只有在被调用时才会进行查询。

因此create_multipliers函数返回的lambda函数被调用时,会在附近的作用域中查询变量i的值,而在create_multipliers生成返回数组之后,整数i的值是4,不会再改变,因此返回数组中每个匿名函数实际上都是:lambda x: 4*x。、

解决办法是将临时值也保存在匿名函数的作用域内,在声明匿名函数时就查询变量的值。

了解原理之后,让我们来改一改代码,surprise!

def create_multipliers():

return [lambda x, i=i : i * x for i in range(5)]

for multiplier in create_multipliers():

print (multiplier(2))

0

2

4

6

8

5. 名称与Python标准库模块发生冲突

Python拥有大量的库模块,开箱即用。但是,如果您遇到一个模块的名称与Python附带的标准库中具有相同名称的模块之间的名称冲突,则可能会出现问题。

例如导入另一个库,而这个库又会尝试导入模块的Python标准库版本,但由于你有一个同名的模块,另一个包会错误地导入你的版本而不是Python标准库。

因此,应该注意避免使用与Python标准库模块中相同的名称,并且更改包中的模块名称比提交Python Enhancement Proposal(PEP)以请求名称更改更容易。

6.is和==/=和==

Python中有很多运算符,例如is,=,==这三个,许多刚刚入门的新手会误解这三个运算符的意义和用法,以致于代码出错。

在 Python 中会用到对象之间比较,可以用 ==,也可以用 is,但对对象比较判断的内容并不相同,区别在哪里?

·is 比较两个对象的 id 值是否相等,是否指向同一个内存地址,== 比较的是两个对象的内容是否相等,值是否相等;

a = [“Python”]

b = a

b is a

True

id(a)

2222222

id(b)

2222222

b == a

True

可以发现上面的例子当中b和a的内存地址是相同的,它们指向同一块内存,因而 is 和 == 的结果都为True,这是因为直接赋值都是赋值的引用。如果新建对象之后,b 和 a 指向了不同的内存,那么 b is a 的结果为False,而 b==a的结果为True。

·小整数对象[-5,256]在全局解释器范围内被放入缓存供重复使用,例如:

a = 1

b = 1

a is b

True

a == b

True

a = 257

b = 257

a is b

False

Python仅仅对比较小的整数对象进行缓存(范围为范围[-5, 256])缓存起来,而并非是所有整数对象。需要注意的是,这仅仅是在命令行中执行,而在Pycharm或者保存为文件执行,结果是不一样的,这是因为解释器做了一部分优化。

=和==的含义不同:

=代表的含义是赋值,将某一数值赋给某个变量,比如a=3,将3这个数值赋予给a。

==是判断是否相等,返回True或False,比如1==1。他们是相等的,那么就返回true。1==2,他们是不相等的,那么就返回false。

例子:

a = [1,2]

b = [1,2]

c = a

a is b

False

a is c

true

a == b

true

7. 滥用__init__

init__方法在Python中用作构造函数,当Python将内存分配给新的类对象时,它会自动被调用。

首先,init__并不相当于C#中的构造函数,在执行它的时候,实例已经构造出来。

class A(object):

def init(self,name):

self.name=name

def getName(self):

return A+self.name

执行代码:

a=A(hello)

可以理解为:

a=object.new(A)

A.init(a,hello)

即__init__作用是初始化已实例化后的对象。

其次,子类可以不重写__init,实例化子类时,会自动调用超类中已定义的__init

class B(A):

def getName(self):

return B+self.name

if name==main:

b=B(hello)

print (b.getName())

但如果重写了__init__,实例化子类时,则不会隐式的再去调用超类中已定义的__init__。

class C(A):

def init(self):

pass

def getName(self):

return C+self.name

if name==main:

c=C()

print (c.getName())

此时执行代码则会报"AttributeError:  C  object has noattribute  name ”错误,所以如果重写了__init__,为了能使用或扩展超类中的行为,最好显式的调用超类的__init__方法。

class C(A):

def init(self,name):

super(C,self).init(name)

def getName(self):

return C+self.name

if name==main:

c=C(hello)

print (c.getName())

老天爷都给我点赞了,你还不点?觉得这篇文章对你有所帮助的话可以来个一键三连呀!!若有指正的话可以评论区见或者私我呀。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容