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对象与类型进行比较是什么意思?
答案 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
,因此它不会调用自身,所以没有递归。