【问题标题】:Duck typing and use of hasattr鸭子打字和hasattr的使用
【发布时间】:2013-03-02 08:08:11
【问题描述】:

我见过很多次这样的事情:

def parse(text):
    if hasattr(text, 'read'):
        text = text.read()

    # Parse the text here...

但如果我传递以下类的实例,它肯定会失败:

class X(object):
    def __init__(self):
        self.read = 10

我的问题是:最pythonic的方式是什么?

我一直在考虑两种主要方式:

if hasattr(text, 'read') and callable(text.read):
    text = text.read()

try:
    text = text.read()
except ...

【问题讨论】:

  • 一般只在你无法控制是否出错时才使用try...except。如果您可以保证通话会正常进行(就像您对callable() 所做的那样,我会认为这是对try...except 的不当使用。

标签: python duck-typing hasattr


【解决方案1】:

pythonic 的方法是假设text 是任何合适的类型。如果您知道 text 在不同的时间会是完全不同的东西,请仅使用 try-except/hasattr

换句话说,不验证。如果你要去else,只使用if,如果你真的想在except中进行特殊处理,请使用try

【讨论】:

  • hmmm.. 在我的示例中,它完全可以是一个接收文件或文本的函数。我在过去见过这种情况(比如re.sub,其中repl 可以是字符串或可调用对象)。
  • 是的,我也在思考。编辑了答案。这些功能属于第二种情况
  • 也许是因为我的英语,但根据你的回答,在我的例子中我应该怎么做?
  • @Oscar 没什么,如果对象在执行期间没有提供您需要的一切,就让它失败。唯一的例外是,如果你有两个不同的代码路径来表示字符串和列表,在这种情况下你显然必须检查类型,但即使那样也不要努力。如果某些东西看起来很像字符串,只需将其作为字符串处理即可。
  • @Voo +1。像你的评论这样的东西就是我想要的。您可以将其发布为答案吗?
【解决方案2】:

pythonic 的方式是检查对象的类型。一方面,该语言足够复杂,以至于您很难确保不包含任何以后无论如何都会失败的对象(您帖子中的明显示例:您不检查函数是否接受 0 个参数,甚至不考虑一下返回类型),而且 - 更糟糕的是 - 你很容易错误地排除有效代码。

最好只假设输入值正常,如果结果不正常,稍后会失败。

实际上只有一个例外:假设您对不同的类型(例如字符串/列表)有不同的代码路径,在这种情况下,您必须检查类型以决定采用哪条路径。但同样:尝试最适合您的通用检查(即,如果 isinstance(l, collections.Iterable) 也可以完成这项工作,则不要检查 isinstance(l, list))。如果后来发现“字符串”不够细,那么你总是会失败。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 2011-03-23
    • 2011-06-13
    • 1970-01-01
    • 2015-08-01
    • 2011-09-28
    • 2012-10-26
    相关资源
    最近更新 更多