鸭子打字和使用hasattr

时间:2013-03-14 04:49:51

标签: python duck-typing hasattr

我见过很多次:

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 ...

2 个答案:

答案 0 :(得分:4)

pythonic方式是假设text属于任何适合的类型。如果您知道 try-except在不同时间完全不同,则只能使用hasattr / text

换句话说,不验证。如果您要if,则仅使用else;如果您真的需要try中的特殊处理,则仅使用except

答案 1 :(得分:2)

pythonic方式检查对象的类型。对于一个语言足够复杂,你将很难确保不包括任何以后会失败的对象(从你的帖子明显的例子:你不检查该函数是否采用0参数,甚至不考虑返回类型), - 更糟糕的是 - 你可以轻易地排除有效代码。

最好只假设输入值是正常的,如果事实证明它们不是,则会失败。

实际上只有一个例外:假设您有不同类型的不同代码路径(比如字符串/列表),在这种情况下,您必须检查类型以确定要采用的路径。但请再次:尝试最适合您的一般检查(即,如果isinstance(l, list)也可以执行此操作,请不要检查isinstance(l, collections.Iterable)。如果它后来证明“字符串”不够真实,那么你总是会失败。