首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python中的常见陷阱

Python中的常见陷阱
EN

Stack Overflow用户
提问于 2009-06-18 08:19:11
回答 33查看 21.1K关注 0票数 79

今天,我再次被多年后可变的默认参数所困扰。除非需要,否则我通常不会使用可变的默认参数,但我想随着时间的推移,我忘记了这一点。今天在应用程序中,我在PDF生成函数的参数列表中添加了tocElements=[],现在在每次调用"generate pdf“之后,”目录“变得越来越长。:)

我还应该在我的清单中添加什么必须避免的东西?

  • 不使用范围代替列表,因为range()无论如何都会变成迭代器,以下代码将失败:

myIndexList = 0,1,3 isListSorted = myIndexList == range(3) #将在3.0中失败isListSorted = myIndexList == list(range(3)) #不会

同样的事情也可以错误地用xrange来完成:

myIndexList == xrange(3)

  • 注意捕获多个异常类型:

尝试:提高KeyError("hmm bug"),KeyError除外,TypeError:打印TypeError

这将打印"hmm bug",尽管它不是一个bug;看起来我们正在捕获这两种类型的异常,但是我们只将KeyError作为变量TypeError来捕获,请使用以下代码:

尝试:提高错误(“hmm KeyError”),除非(KeyError,TypeError):print TypeError

EN

回答 33

Stack Overflow用户

发布于 2009-08-24 08:17:26

不要使用索引在序列上循环

不要:

代码语言:javascript
复制
for i in range(len(tab)) :
    print tab[i]

执行以下操作:

代码语言:javascript
复制
for elem in tab :
    print elem

For将为您自动执行大多数迭代操作。

如果确实需要索引和元素,请使用enumerate

代码语言:javascript
复制
for i, elem in enumerate(tab):
     print i, elem

使用"==“检查 True False时要小心

代码语言:javascript
复制
if (var == True) :
    # this will execute if var is True or 1, 1.0, 1L

if (var != True) :
    # this will execute if var is neither True nor 1

if (var == False) :
    # this will execute if var is False or 0 (or 0.0, 0L, 0j)

if (var == None) :
    # only execute if var is None

if var :
    # execute if var is a non-empty string/list/dictionary/tuple, non-0, etc

if not var :
    # execute if var is "", {}, [], (), 0, None, etc.

if var is True :
    # only execute if var is boolean True, not 1

if var is False :
    # only execute if var is boolean False, not 0

if var is None :
    # same as var == None

如果可以,请不要检查,只需执行此操作并处理错误

Pythonistas通常会说“请求宽恕比请求许可更容易”。

不要:

代码语言:javascript
复制
if os.path.isfile(file_path) :
    file = open(file_path)
else :
    # do something

执行以下操作:

代码语言:javascript
复制
try :
    file =  open(file_path)
except OSError as e:
    # do something

或者使用python 2.6+ /3做得更好:

代码语言:javascript
复制
with open(file_path) as file :

它更好,因为它更具通用性。你可以将"try / except“应用到几乎任何东西上。你不需要关心做什么来防止它,只需要关心你冒着错误的风险。

不检查类型

Python是动态类型的,因此检查类型会使您失去灵活性。取而代之的是,通过检查行为来使用鸭子类型。例如,您希望在函数中包含字符串,然后使用str()将字符串中的任何对象转换为字符串。你需要一个列表,使用list()来转换列表中的任何可迭代对象。

不要:

代码语言:javascript
复制
def foo(name) :
    if isinstance(name, str) :
        print name.lower()

def bar(listing) :
    if isinstance(listing, list) :
        listing.extend((1, 2, 3))
        return ", ".join(listing)

执行以下操作:

代码语言:javascript
复制
def foo(name) :
    print str(name).lower()

def bar(listing) :
    l = list(listing)
    l.extend((1, 2, 3))
    return ", ".join(l)

使用最后一种方法,foo将接受任何对象。Bar将接受字符串、元组、集合、列表等。廉价干货:-)

不要混用空格和制表符

别哭了。你会哭的。

使用 object 作为第一个父

这很棘手,但随着程序的增长,它会咬你一口。Python 2.x中有旧的和新的类。旧的是,好吧,旧的。它们缺少一些功能,而且继承起来可能会有笨拙的行为。为了可用,你的任何一个类都必须是“新风格”的。为此,让它继承自"object“:

不要:

代码语言:javascript
复制
class Father :
    pass

class Child(Father) :
    pass

执行以下操作:

代码语言:javascript
复制
class Father(object) :
    pass


class Child(Father) :
    pass

在Python3.x中,所有的类都是新的风格,所以你可以声明class Father:是好的。

不要在 __init__ 方法之外初始化类属性

来自其他语言的人发现它很诱人,因为这就是您在Java或PHP中所做的工作。您编写类名,然后列出您的属性并给它们一个默认值。它似乎在Python中工作,然而,这并不是你想的那样工作。

这样做将设置类属性(静态属性),然后当您尝试获取对象属性时,它会给出它的值,除非它为空。在这种情况下,它将返回类属性。

这意味着两个大的危险:

  • 如果更改了类属性,则初始值也会更改。
  • 如果将可变对象设置为默认值,则将在实例之间共享相同的对象。

不要(除非你想要静态的):

代码语言:javascript
复制
class Car(object):
    color = "red"
    wheels = [wheel(), Wheel(), Wheel(), Wheel()]

执行以下操作:

代码语言:javascript
复制
class Car(object):
    def __init__(self):
        self.color = "red"
        self.wheels = [wheel(), Wheel(), Wheel(), Wheel()]
票数 73
EN

Stack Overflow用户

发布于 2009-06-22 04:27:30

当您需要一组数组时,您可能会想要键入下面这样的内容:

代码语言:javascript
复制
>>> a=[[1,2,3,4,5]]*4

果然,当你看着它时,它会给你你所期望的

代码语言:javascript
复制
>>> from pprint import pprint
>>> pprint(a)

[[1, 2, 3, 4, 5],
 [1, 2, 3, 4, 5],
 [1, 2, 3, 4, 5],
 [1, 2, 3, 4, 5]]

但是不要期望你的群体中的元素是独立的对象:

代码语言:javascript
复制
>>> a[0][0] = 2
>>> pprint(a)

[[2, 2, 3, 4, 5],
 [2, 2, 3, 4, 5],
 [2, 2, 3, 4, 5],
 [2, 2, 3, 4, 5]]

除非这是你需要的..。

值得一提的是一种解决方法:

代码语言:javascript
复制
a = [[1,2,3,4,5] for _ in range(4)]
票数 39
EN

Stack Overflow用户

发布于 2009-06-18 10:24:09

Python语言Gotchas --以非常隐蔽的方式失败的东西

使用可变的默认arguments.

  • Leading零表示八进制的
  • 。在超类或子类中被Python 2.x
  • Misspelling覆盖的方法名称中,09是一个非常隐蔽的语法错误。超类的拼写错误更严重,因为没有一个子类正确地覆盖它。

Python设计Gotchas

  • 将时间花在自省上(例如,尝试自动确定类型或超类标识或其他内容)。首先,阅读源代码可以明显看出这一点。更重要的是,花费在奇怪的Python自省上的时间通常表明无法掌握多态性。80%的Python自省问题都是在代码高尔夫上无法获得Polymorphism.
  • Spending时间。仅仅因为你的应用程序的心理模型是四个关键字(" do ","what","I"," mean "),并不意味着你应该构建一个超复杂的自省装饰器驱动的框架来做到这一点。Python允许您将枯燥程度提高到愚蠢的程度。上剩下的Python自省问题试图减少复杂的问题,通过编写高尔夫exercises.
  • Monkeypatching.
  • Failure来实际读取标准库,并使用适当的程序重新发明wheel.
  • Conflating交互式类型。当您以交互方式键入时,可能会丢失变量的跟踪信息,因此必须使用globals()。而且,当你打字的时候,几乎所有的东西都是全局的。在适当的程序中,您永远不会“失去对变量的跟踪”,而且没有任何东西是全局的。
票数 28
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1011431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档