Python pytyping感觉笨重的是这个Pythonic?

时间:2014-05-25 00:37:31

标签: python python-3.x duck-typing

Python 3

数据可能是字符串,字节或EmailMessage。

这是从数据中获取字节数的最有效方法吗?

    while True:
        try:
            # data is a string
            f.write(data.encode('utf-8'))
            break
        except:
            pass
        try:
            # data is an EmailMessage
            f.write(data.get_bytes())
            break
        except:
            pass
        try:
            # data is bytes
            f.write(data)
            break
        except:
            pass
        else:
            self.log.info('Exiting, unknown attachment type')
            sys.exit(1)

2 个答案:

答案 0 :(得分:7)

if hasattr(data, "encode"):
    f.write(data.encode('utf-8'))
elif hasattr(data, "get_bytes"):
    f.write(data.get_bytes())
else:
    try:
        f.write(data)
    except TypeError:
        self.log.info('Exiting, unknown attachment type')
        sys.exit(1)

修改

这就像鸭子一样 - “如果它像鸭子一样嘎嘎叫,它就是一只鸭子;如果它编码,它就是一个字符串”。

这比if isinstance(data, str)优先,因为限制较少;只要一个对象知道如何将自己编码为字节,我们并不关心它是否实际上是一个字符串。

异常相对较慢,应保留用于处理意外或不太可能的错误。

答案 1 :(得分:1)

来自维基百科:

  

例如,在非鸭类型语言中,可以创建一个函数   这要求传递给它的对象按顺序为Duck类型   确保该功能可以使用对象的步行和嘎嘎声   方法。在鸭子类型的语言中,该函数将采用一个对象   任何类型的,只需调用其walk和quack方法,生成一个   如果未定义运行时错误。鸭子打字实践不是正式指定类型,而是依赖于文档,清晰的代码和测试以确保正确使用

这并不意味着你可以调用你想要的任何方法,如果它不存在则会发现异常。你仍然需要努力只调用你确定会在那里的方法。鸭子打字与你不关心对象的类型(如果你把它传递给一个函数,你没有像在Java中那样指定类型)这一事实更相关,但是仍然确定它会响应特定的方法调用。

在您的情况下,我要做的是使用公共方法get_data围绕每个对象(String,EmailMessage,bytes)创建一个包装器,其中get_data的每个实现都特定于对象的类型它包裹着(encodeget_bytes等。然后你的循环看起来如下:

while True:
    try:
        # data is a string
        f.write(data.get_data())
        break
    except:
        pass

修改:您可能还希望看到与您的问题相关的问题:How to handle "duck typing" in Python?