2016-02-02 2 views
1

Учитывая функцию:Как анонимный список работает в понимании списка python?

def merge(nums1, nums2): 
    return [max(nums1, nums2).pop(0) for _ in nums1 + nums2] 

Я думаю, что это работает, как:

def merge(nums1, nums2): 
    ans = [] 
    while nums1 or nums2: 
     if nums1 > nums2: 
      ans += nums1[0], 
      nums1 = nums1[1:] 
     else: 
      ans += nums2[0], 
      nums2 = nums2[1:] 
    return ans 

Функция принимает максимум текущего значения в крайнем левом nums1 и num2 и добавляет его в новый массив.

Может ли кто-нибудь объяснить мне, почему первый из них эквивалентен второму? В частности, часть:

for _ in nums1 + nums2 

путает меня больше всего.

Подобные те хотели, чтобы инициализировать массив размера п:

[0 for _ in xrange(n)] 

Я понимаю, что

for _ in xrange(n) 

просто говорит, чтобы выполнить п раз, и заполнить массив с возвращаемым значением из выражения до для аналогично,

for _ in nums1 + nums2 

выполнить len (nums1) + len (nums2) раз, но если мы pop, длина должна измениться.

Так почему же я неправильно понял? Это то, что часть после в статье является копией оригинала?

+0

Вы объяснили код. Есть только что-то, что вы пропустили. 'num1 + num2' оценивается только один раз в начале. Это приводит к появлению нового анонимного списка, который цикл повторяется. Изменения одной из двух переменных в цикле больше не влияют на цикл. –

+0

Этот код не только обфускается, но и не эффективно выполняет свою функцию. 'pop (0)' требует, чтобы весь список был смещен в памяти, что делает этот O (n * n) –

ответ

3

Q1:

Может кто-нибудь объяснить мне, почему первый один эквивалентно второй?

A1:

Мы можем использовать эту функцию и наблюдать кое-что:

>>> a = [1,2,3] 
>>> b = [4,0,5] 
>>> 
>>> print merge(a,b) 
[4, 1, 2, 3, 0, 5] 
>>> a 
[] 
>>> b 
[] 

max(nums1, nums2).pop(0) должен сравнить первые элементы обоих списков. Всякий раз, когда он выполняет одно время цикла, он выдает первый элемент максимального списка. Фактически, max возвращает объект, используя ссылку на память, поэтому оба списка будут постепенно уменьшать свои элементы utils, заканчивающиеся for-loop. Поэтому поэтому a и b переменные пусты после завершения функции.

Позвольте мне показать, как работать.

>>> a = [1,2,3] 
>>> b = [4,0,5] 
>>> merge1(a,b) 
Step1 
nums1: [1, 2, 3] 
nums2: [4, 0, 5] 
The max list is [4, 0, 5] 
So it will pop : 4 
Step2 
nums1: [1, 2, 3] 
nums2: [0, 5] 
The max list is [1, 2, 3] 
So it will pop : 1 
Step3 
nums1: [2, 3] 
nums2: [0, 5] 
The max list is [2, 3] 
So it will pop : 2 
Step4 
nums1: [3] 
nums2: [0, 5] 
The max list is [3] 
So it will pop : 3 
Step5 
nums1: [] 
nums2: [0, 5] 
The max list is [0, 5] 
So it will pop : 0 
Step6 
nums1: [] 
nums2: [5] 
The max list is [5] 
So it will pop : 5 
[4, 1, 2, 3, 0, 5] 

И я прилагаю мой код:

def merge1(nums1, nums2): 
    list_ = [] 
    count = 1 
    for _ in nums1 + nums2: 
     print 'Step%s' % count 
     print 'nums1: ' , nums1 
     print 'nums2: ' , nums2 
     print 'The max list is ', max(nums1, nums2) 
     print 'So it will pop :', max(nums1, nums2)[0] 
     list_.append(max(nums1, nums2).pop(0)) 
     count +=1 
    return list_ 

В соответствии с рабочим процессом, вы увидите max(nums1, nums2).pop(0) эквивалентно ans += nums1[0];nums1 = nums1[1:]; или ans += nums2[0];nums2 = nums1[1:];.


Q2:

для _ в nums1 + nums2 выполнить LEN (nums1) + Len (nums2) раз, но если мы поп, длина должна изменилась.

А2:

Нет, после для цикла считывает номер или объект, как выполнение подсчета, то pop не может динамически влиять на выполняющийся подсчете.

Я могу предложить эквивалентный код для вас.

def merge1(nums1, nums2): 
    return [max(nums1, nums2).pop(0) for _ in range(len(nums1) + len(nums2)] 

демо:

>>> a = [1,2,3] 
>>> b = [4,0,5] 
>>> print merge1(a,b) 
[4, 1, 2, 3, 0, 5] 

Так это случилось? Ничего.


Q3:

В частности, часть: для _ в nums1 + nums2

A3:

По моим A2, вы можете изображения его for _ in range(len(nums1) + len(nums2), они эквивалентны. Цикл for-loop просто хочет, чтобы число элементов выполнялось как счетчик.

2

Ключ недопонимание в том, что это:

for _ in nums1 + nums2 

создает новый список, который повторяется снова. Этот код может быть написан как так точно такой же эффект:

def merge(nums1, nums2): 
    another_list = nums1 + nums2 
    return [max(nums1, nums2).pop(0) for _ in another_list] 

Как вы можете видеть, another_list никогда не меняется, даже nums1 и nums2 медленно едят.

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