2016-04-21 3 views
0
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, youtube-dl. В эффекте, чтобы стать лучшим программистом, я кулаком по этому разделу, и мне трудно понять его.Как работает этот конкретный раздел кода?

В частности, последний метод и то, как он не вводит бесконечную рекурсию, если ie_key не найден в списке.

Как и сравнение isinstance в первом методе.

Я понимаю, что нормальная реализация является чем-то вроде: isinstance ('hello', str), но как может type() быть типом? Более того, в чем смысл сравнения типа ie с типом?

+0

Я бы предположил, что _ies_instances является dict, и в какой-то момент сделал что-то вроде 'self._ies_intances [None] = var' – JETM

+0

Он вводит бесконечную рекурсию ... – Bharel

ответ

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

Я считаю, что причина этого позволяет избежать бесконечной рекурсии, так это то, что это никогда не происходит вообще! Присмотритесь:

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

Обратите внимание, что get_info_extractor определение которого мы читаем является метод, и он вызывает функцию, не метод, который просто так случается быть также назван get_info_extractor, и поэтому он не называет себя, и поэтому нет рекурсии.

Смежные вопросы