2016-07-06 2 views
1

Я начал изучать Python. Я очень путаюсь с одним слоем, используемым в этом коде (5-я строка в приведенном ниже коде).Python: Как написать этот python one-liner в «удобочитаемом» виде?

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

multiset = [2, 2, 3, 3, 4, 5, 6, 7, 8, 10] 
x = [0] 
deltaSet = set(multiset) 

for candidate in deltaSet:    
    if sum([(abs(candidate-member) in multiset) for member in x]) == len(x): 
     for member in x:        
      multiset.remove(abs(candidate-member)) 
     x.append(candidate) 
     if len(x) == n: break 

Спасибо!

+0

Похоже, что этот код использует расширенную функцию, называемую пониманием списка. Понятно, что человек, новый для Python, не поймет. – u8y7541

+0

Вот что я подумал, он должен использовать некоторую расширенную функцию python. Не могли бы вы переписать простую форму? – Retr0spect

+0

Код не детерминирован, так как результат зависит от порядка итерации по deltaSet. Это заставляет меня думать, что это неправильно, что бы это ни было. –

ответ

7

Я считаю, что линия вы смотрите на это:

sum([(abs(candidate-member) in multiset) for member in x]) 

Во-первых, слишком много скобку там. Давайте избавимся от вещей, которые нам не нужны:

sum(abs(candidate-member) in multiset for member in x) 

Фу, это уже немного лучше. Теперь давайте реально смотреть на выражения поштучно:

abs(candidate - member) in multiset 

Это само достаточно толковый ... Является ли абсолютное значение кандидата минус член в мультимножестве? Если да, выражение возвращает True, если нет, выражение возвращает False. Теперь что такое member? Ну, есть одна для каждой вещи в iterable x. Итак, вы суммируете кучу True и False. В python булевы подклассы от intTrue == 1 и False == 0), сумма в основном рассчитывает количество раз, о котором мы говорили ранее, - True.

Затем они проверяют, если она равна len(x) поэтому в основном, код проверки, если выражение True для каждого члена в x. К счастью, есть лучший способ, чтобы написать это в Python:

all(abs(candidate - member) in multiset for member in x) 

Если это все еще сбивает с толку, мы могли бы переписать в виде функции (позволяет называть его f(x):

def f(x): 
    """Equivalent to `all(abs(candidate - member) in multiset for member in x.""" 
    for member in x: 
     if not abs(candidate - member) in multiset: 
      return False 
    return True 

Для некоторого опорного чтения, в обоих случаях я использовал выражения генератора (которые аналогичны list-comprehensions в синтаксисе и значении, но они генерируют элементы «уступят» «на лету», а не материализуют весь список за один раз. Они более эффективны и быстрее для памяти некоторые операции. Они особенно полезны для случаев, когда вам не нужно смотреть на каждый предмет, чтобы знать результат (например, этот, где достаточно всего False, чтобы сделать все выражение False).

+0

Большое спасибо за подробное объяснение. Это действительно помогло мне понять код. Сумма/все еще меня путает. Можете ли вы написать это Java, используя несколько циклов? – Retr0spect

+0

@ Retr0spect - я не уверен, что могу написать его на Java, потому что я не очень хорошо знаю Java, и я не помню, как сделать цикл forEach на Java (или если вы даже можете ...). Я _can_ (и имею) написал выражение 'all' как очень базовую функцию python.Надеюсь, это полезно. – mgilson

+0

Поблагодарите mgilson, я очень ценю вашу помощь. Изменить: я переписал код на Java, но по какой-то причине он не дает ожидаемого результата. Я не могу понять, что я делаю неправильно. – Retr0spect

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