Почему python reduce() пропускает элемент None?

Я попытался получить домашний сайт URL-адреса. Сначала я использовал цикл for и достиг цели.

home = ''
my_url = 'http://www.mysite.com/subdir/subdir2/index.html'
for item in my_url.split('/')[:3]:
    home += item + '/'
print  home

и я могу получить

'http://www.mysite.com/' 

Затем я наткнулся на метод reduce(), который никогда раньше не использовал. Итак, я понял, вот код:

my_url = 'http://www.mysite.com/subdir/subdir2/index.html'
home = ''
home = reduce(lambda x,y : x + y + '/',my_url.split('/')[:3])
print home

на этот раз я получил

'http:/www.mysite.com/'

Это уменьшить, просто опустив в нем None? Каково объяснение результата?

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


person Allan Ruin    schedule 20.02.2012    source источник
comment
вы должны использовать filter() для удаления элементов None   -  person sherpya    schedule 20.02.2012
comment
@sherpya Нет, я не хочу опускать элемент None, я смущен тем, что функция reduce () пропускает элемент None и оставляет результат как «http:/www.mysite.com/», который должен быть « mysite.com'   -  person Allan Ruin    schedule 20.02.2012
comment
reduce ничего не пропускает. Элемента None нет. Как вы думаете, где это происходит?   -  person Michael J. Barber    schedule 20.02.2012
comment
Это очень плохой способ использования reduce(). Кроме того, было бы ошибкой не использовать для этого urllib. Я предлагаю закрыть этот вопрос, потому что он вводит в заблуждение. Вопрос очень и очень запутанный.   -  person S.Lott    schedule 20.02.2012
comment
Прошу прощения за то, что не описал проблему четко. По вашему мнению, я знаю, что неосознанно принял ''(пустую строку) как None. Но результат reduce() действительно вызвал у меня много путаницы, потому что я не знаком с сокращением и, читая документ, я до сих пор не совсем понимаю, как работает функция reduce(). Объяснение Марсина ясное и точное, и теперь я лучше понимаю процесс сокращения().   -  person Allan Ruin    schedule 20.02.2012


Ответы (2)


my_url = 'http://www.mysite.com/subdir/subdir2/index.html'
home = ''
home = reduce(lambda x,y : x + y + '/',my_url.split('/')[:3])

my_url.split('/')[:3] #=> ['http:', '', 'www.mysite.com']

'http:' + '' + '/' #=> 'http:/'
'http:/' + 'www.mysite.com' + '/' #=> 'http:/www.mysite.com/'

Это не таинственно. Все работает как положено - проблема в том, что URL-адреса неоднородны, протоколы разделены двойной косой чертой.

Полезным инструментом для понимания того, как работает сокращение, является scanl из functional ( http://pypi.python.org/pypi/functional ):

In [11]: home = scanl(lambda x,y : '%s%s/'%(x,y),my_url.split('/')[0],my_url.split('/')[1:3])

In [12]: home
Out[12]: <generator object _scanl at 0x0000000003DEC828>

In [13]: list(home)
Out[13]: ['http:', 'http:/', 'http:/www.mysite.com/']

Обратите внимание, что str.join реализует немного другой алгоритм:

In [16]: '/'.join(my_url.split('/'))
Out[16]: 'http://www.mysite.com/subdir/subdir2/index.html'

Это то, что люди обычно хотят - это эквивалентно:

In [22]: reduce(lambda x,y : '%s/%s'%(x,y),my_url.split('/'))
Out[22]: 'http://www.mysite.com/subdir/subdir2/index.html'
person Marcin    schedule 20.02.2012
comment
Вот точное объяснение! Спасибо~ - person Allan Ruin; 20.02.2012
comment
На самом деле, URL-адреса не являются единообразными, это не проблема. Подход с reduce работает, если вместо этого мы делаем lambda x, y: x + '/' + y, чтобы косая черта помещалась между компонентами, а не после каждого, кроме первого. Конечно, в этом случае косой черты в конце не будет. - person Karl Knechtel; 14.03.2012
comment
@KarlKnechtel Вы понимаете, что эта информация уже есть в моем ответе? - person Marcin; 14.03.2012
comment
В конце да, но объяснение кажется мне немного неуклюжим. - person Karl Knechtel; 14.03.2012

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

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

В любом случае, вернемся к вашему вопросу: когда я набираю: my_url.split('/')[:3], я получаю следующее:

['http:', '', 'www.mysite.com']

Так что в нем нет None, просто пустая строка, которую можно использовать как любую другую строку. И, по-видимому, это то, что делает ваша лямбда-функция для алгоритма reduce, она просто объединяет строки вместе. Я предлагаю вам использовать метод strings join, так как он более читабелен и понятен:

>>> parts = my_url.split('/')[:3]
>>> print "/".join(parts)
'http://www.mysite.com'

Однако вы должны добавить последний / самостоятельно.

person Constantinius    schedule 20.02.2012
comment
спасибо Константиниус. Я просто пытаюсь найти случай, когда можно использовать reduce(). Поскольку я знаю, что для этого уже есть urllib, мне не нужно будет использовать этот моментальный снимок «колеса». - person Allan Ruin; 20.02.2012