Python Duck类型和hasattr的使用

Python Duck类型和hasattr的使用,python,duck-typing,hasattr,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 我的问题是:处理它的最有吸引力的方式是什么 我一直在考虑两个主要的方法: if has

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

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

    # Parse the text here...
但如果我通过了以下类的实例,它肯定会失败:

class X(object):
    def __init__(self):
        self.read = 10
我的问题是:处理它的最有吸引力的方式是什么

我一直在考虑两个主要的方法:

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


python的方法是假设
文本
是任何适合的类型
。如果您知道
文本
在不同的时间将是完全不同的内容,则只能使用
尝试除
/
hasattr


换句话说,不验证。如果你想在
中使用
if
,如果你真的想在
中进行特殊处理,除了
,之外,只使用
if
,如果你真的想在
中进行特殊处理,
尝试
,python的方法是假设
文本
是任何适合的类型。如果您知道
文本
在不同的时间将是完全不同的内容,则只能使用
尝试除
/
hasattr

换句话说,不验证。如果您想在
中进行特殊处理,请仅在
中使用
如果您确实想在
中进行特殊处理,请尝试
,pythonic方法根本不检查对象的类型。首先,该语言非常复杂,您将很难确保不包含任何稍后将失败的对象(从您的帖子中可以看到一个明显的例子:您不检查函数是否包含0个参数,甚至不考虑返回类型),而且更糟糕的是,您很容易错误地排除有效代码

最好是假设输入值是正常的,如果结果不是这样,则稍后会失败

实际上只有一个例外:假设您对不同的类型(比如字符串/列表)有不同的代码路径,在这种情况下,您必须检查类型以决定采用哪条路径。但是,请再次尝试最通用的检查方法(即,如果
isinstance(l,list)
isinstance(l,collections.Iterable)
也可以执行此操作,则不要检查
isinstance(l,collections.Iterable)。如果后来发现“string”不够严格,那么您总是会失败。

python方法根本不检查对象的类型。首先,该语言非常复杂,您将很难确保不包含任何稍后将失败的对象(从您的帖子中可以看到一个明显的例子:您不检查函数是否包含0个参数,甚至不考虑返回类型),而且更糟糕的是,您很容易错误地排除有效代码

最好是假设输入值是正常的,如果结果不是这样,则稍后会失败


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

hmmm。。在我的示例中,它完全可以是一个接收文件或文本的函数。在过去我看到过(比如
re.sub
,其中
repl
可以是字符串,也可以是可调用的)。编辑了答案。这些函数属于第二种情况可能是因为我的英语,但是根据你的回答,在我的示例中我应该做什么?@Oscar Nothing,如果对象在执行过程中没有提供你所需要的一切,就让它失败吧。唯一的例外是,如果字符串和列表有两个不同的代码路径,那么显然必须检查类型,但即使这样,也不要尝试太过努力。如果某个东西看起来很像字符串,就把它当作字符串来处理。@Voo+1。像你这样的评论正是我想要的。你能把它贴出来作为答案吗?嗯。。在我的示例中,它完全可以是一个接收文件或文本的函数。在过去我看到过(比如
re.sub
,其中
repl
可以是字符串,也可以是可调用的)。编辑了答案。这些函数属于第二种情况可能是因为我的英语,但是根据你的回答,在我的示例中我应该做什么?@Oscar Nothing,如果对象在执行过程中没有提供你所需要的一切,就让它失败吧。唯一的例外是,如果字符串和列表有两个不同的代码路径,那么显然必须检查类型,但即使这样,也不要尝试太过努力。如果某个东西看起来很像字符串,就把它当作字符串来处理。@Voo+1。像你这样的评论正是我想要的。你能把它贴出来作为答案吗?通常只使用
try…除非你无法控制是否出了问题。如果您可以保证调用将起作用(正如您对 Calable()/代码>所做的那样,我会考虑使用<代码>尝试……除了。一般只使用<代码>尝试……除了< /代码>之外,当您无法控制是否出错时,如果您可以保证调用将起作用(正如您使用的 Cabable()所做的那样。,我认为不正确使用<代码>尝试…除了。
try:
    text = text.read()
except ...