python - 在这种情况下,如何平衡 "Pythonic"和 "convenient"?

标签 python duck-typing

我有一个将由客户端代码实现的“接口(interface)”:

class Runner:
    def run(self):
        pass

run 通常应该返回一个 docutils node 但因为 far far most 常见情况是纯文本,调用者允许 run 返回一个字符串,这将是 使用 type() 检查并变成一个 node

但是,按照我对“Pythonic”的理解,这不是“Pythonic”,因为 检查某物的 type() 不会让它通过“表现”而“成为”一种类型 一——即“Pythonic”代码应该使用鸭子类型(duck typing)。

我考虑过

def run_str(self):
    pass

def run_node(self):
    return make_node(self.run_str())

但我不关心这个,因为它把不那么有趣的返回类型 就在名字里;这让人分心。

有什么我错过的想法吗?另外,有没有我可能会遇到的问题 在我的“坏”系统的道路上(对我来说似乎或多或少安全)?

最佳答案

我认为这是一个有点欺骗性的例子;有件事你没说。我猜当你说你“有一个接口(interface)”时,你的意思是你有一些代码接受一个对象并调用它的 run 方法。

如果您在调用对象的 run 方法之前没有测试该对象的类型,那么您就是在使用鸭子类型(duck typing),简单明了! (在这种情况下,如果它有一个 run 方法,那么它就是一个 Runner。)只要你不使用 typeisinstance 在对象上使用 run 方法,那么你就是 Pythonic。

您是应该接受纯字符串还是只接受节点对象是一个略有不同的问题。字符串和 node 对象可能根本不实现相同的接口(interface)!从根本上说,字符串不会节点那样嘎嘎作响,因此您不必像对待一个节点那样对待它们。这就好比一头大象来了,要想它像鸭子类型(duck typing)一样嘎嘎叫,就得先给大象一个录音机,先训练大象使用它。

所以这不再是“鸭子类型(duck typing)”的问题,而是界面设计的问题。您正在尝试决定您希望界面的严格程度。

为了给你一个答案,那么,在这个层面上,我认为最 Pythonic 的假设是 run 返回一个 node 对象。无需使用 isinstancetype 对其进行测试。假设它是一个 node 对象,如果使用您的界面的程序员弄错了,并看到异常,那么他们将不得不阅读您的文档字符串,这将告诉他们 run 应该传递一个 node 对象。

然后,如果您也接受字符串,或者像字符串一样嘎嘎作响的东西,您可以这样做。由于字符串是相当原始的类型,我认为使用 isinstance(obj, basestring) 并没有什么不合适的(但不是 type(obj) == str 因为它拒绝 unicode 字符串等)。从本质上讲,这是您对程序的懒惰用户非常慷慨和友善;你已经超越了接受大象以及像鸭子类型(duck typing)一样嘎嘎叫的东西。

(更具体地说,我想说这有点像在您想要同时接受生成器和序列的函数开头的参数上调用 iter。)

关于python - 在这种情况下,如何平衡 "Pythonic"和 "convenient"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7102242/

相关文章:

python - 为什么我不能将 join 用于实现 __str__ 的对象列表?

python - 使用 .join 函数从列表中连接 python 字符串不会输出想要的结果

Javascript方式设计继承+隐私

python - 为什么某些正则表达式引擎会在单个输入字符串中匹配 .* 两次?

python - 字符/数字的边界框检测

戈朗 : Can you wrap a Package in an Interface?

python : using type hints to dynamically check types

Ruby 的 'is_a?' 为内置类型返回 false,这是怎么回事?

python - 如何在迭代时从列表中删除项目?

python - 使用 XlsxWriter 模块修改图表标签方向 (Python)