这段特定代码如何工作?

时间:2016-04-21 19:30:20

标签: python

def add_info_extractor(self, ie):
    """Add an InfoExtractor object to the end of the list."""
    self._ies.append(ie)
    if not isinstance(ie, type):
        self._ies_instances[ie.ie_key()] = ie
        ie.set_downloader(self)

def get_info_extractor(self, ie_key):
    """
    Get an instance of an IE with name ie_key, it will try to get one from
    the _ies list, if there's no instance it will create a new one and add
    it to the extractor list.
    """
    ie = self._ies_instances.get(ie_key)
    if ie is None:
        ie = get_info_extractor(ie_key)()
        self.add_info_extractor(ie)
    return ie

以下内容来自流行的python repo,youtube-dl。为了成为一名更好的程序员,我突然想到这一部分,我无法理解它。

特别是最后一个方法,如果在列表中找不到ie_key,它怎么不进入无限递归。

与第一种方法中的实例比较一样。

我理解正常的实现是有效的:isinstance('hello',str),但是type()如何成为一个类型?此外,将ie对象与类型进行比较是什么意思?

2 个答案:

答案 0 :(得分:1)

这肯定会导致无限递归。在递归调用之间似乎没有更新self._ies_instances,并且由于递归取决于这种情况,它将继续。

也许这是一个错误,但是当ie_key不在字典中时代码从未出现过这种情况?

至于你与type的混淆,它是Python Metaclasses(很棒的阅读)的结果。 type同时充当"功能"返回对象的类型以及类来创建新类型(使用更多参数调用时)。

您可能想要查看是否某个内容是type的实例的一个原因是查看某些内容是否属于元类:

>>> isinstance(1, type)
False
>>> isinstance("", type)
False
>>> isinstance({}, type)
False
>>> isinstance((), type)
False
>>> type(object) == type
True
>>> isinstance(object, type)
True
>>> isinstance(object(), type)
False
>>> class a(): pass
...
>>> isinstance(a, type)
False
>>> isinstance(a(), type)
False

由于object是所有新款式'的基础。 (docs),它也充当元类(如上所示)。

答案 1 :(得分:1)

我相信这避免了无限递归的原因是它根本就没有真正的递归!仔细观察:

def get_info_extractor(self, ie_key):
    ...
    ie = get_info_extractor(ie_key)()

请注意,我们正在阅读其定义的get_info_extractor是一个方法,并且它调用非方法函数,恰好也被命名为get_info_extractor,因此它不会调用自身,所以没有递归。