Уведомления

Группа в Telegram: @pythonsu

#1 Март 24, 2017 12:38:02

Bilbo
Зарегистрирован: 2017-03-23
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

Продолжаю разбираться с Python. В одном из самоучителей по нему прочитал, что можно складывать только однотипные данные. Речь шла о списках и кортежа. Столкнулся с таким поведением:

 a= ("x","y")
b=["n","p"]

Сложить их не получилось
 с=None
c=a+b
a=a+b
b=a+b
a+=b
Но если сделать запись такого вида:
 b+=a
То она увенчается успехом и мы получим список. Это ожидаемое поведение? В чем здесь нюанс и отличие от b=b+a?
Пользуясь случаем сразу спрошу зачем существуют кортежи, в чем их преимущество перед списками? Знаю, что они неизменяемые, но можно ли это отнести к достоинствам?

Отредактировано Bilbo (Март 24, 2017 12:40:54)

Офлайн

#2 Март 24, 2017 13:07:30

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9726
Репутация: +  843  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

Похоже на баг.

Семантика bytearray() реализована теми же методами, но так не работает.

  
>>> b = bytearray(b'abc')
>>> b
bytearray(b'abc')
>>> b + [1, 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat bytearray to list
>>> b += [1, 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat list to bytearray
>>> b.extend([1, 2])
>>> b
bytearray(b'abc\x01\x02')
>>>

Так что можешь поискать описание чего-то подобного на https://bugs.python.org , просто вопрос там или вопрос с разъяснением. А может ты первый и нашёл это и обратил внимание.

Как-то непредсказуемо выглядит.
  
>>> lst = [1, 2, 3]
>>> 
>>> lst + 'abc'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
>>> 
>>> lst += 'abc'
>>> lst
[1, 2, 3, 'a', 'b', 'c']
>>>



Отредактировано py.user.next (Март 24, 2017 13:13:27)

Офлайн

#3 Март 24, 2017 13:25:00

4kpt_V
От: Харьков
Зарегистрирован: 2017-02-19
Сообщения: 299
Репутация: +  12  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

Эмм. Это никакой не баг
Лучано Ромальо. Python. К вершинам мастерства.

Отредактировано 4kpt_V (Март 24, 2017 13:28:30)

Офлайн

#4 Март 24, 2017 13:38:57

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

> В чем здесь нюанс и отличие от b=b+a?

В том что ты в первом случае пытаешься изменить картеж.

> Пользуясь случаем сразу спрошу зачем существуют кортежи, в чем их преимущество перед списками?

В том что их нельзя изменять.

> Знаю, что они неизменяемые, но можно ли это отнести к достоинствам?

Конечно! ИХМО изменяемые объекты это зло.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#5 Март 24, 2017 14:13:06

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9726
Репутация: +  843  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

4kpt_V
Эмм. Это никакой не баг :)
Лучано Ромальо. Python. К вершинам мастерства.
Это нужно не в книжке смотреть, а в документации. Но тут и без документации понятно, что это поведение не одижаемо для пользователя.
И тут не работает аналог операции - значит, уже что-то не то.

lst = lst + 'abc' - не работает
lst += 'abc' - работает
Хотя вторая операция является сокращённой записью первой операции.



Отредактировано py.user.next (Март 24, 2017 14:14:06)

Офлайн

#6 Март 24, 2017 14:49:37

4kpt_V
От: Харьков
Зарегистрирован: 2017-02-19
Сообщения: 299
Репутация: +  12  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

То, что оно не ожидаемо, это еще не значит, что это баг. Это раз. В делфи вообще тьма тьмущая приведения типов. Просто, в пайтоне этого нет на базовых типах и мы привыкли

вот тут описано почему так происходит

Отредактировано 4kpt_V (Март 24, 2017 15:00:07)

Офлайн

#7 Март 24, 2017 21:21:43

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

py.user.next
Хотя вторая операция является сокращённой записью первой операции.
чето сомнения меня терзают по этому поводу.Поправте если я не прав.
Что происходит когда вы делаете a + b?
Вызывается метод a.__add__(b)
если a.__add__ не определен то вызывается b. __radd__(a)
а когда a+=b то a.__iadd__(b)
логично предположить что в случае топикстартера методы .__add__ и __iadd__ работают по разному.
А вот баг это или фитча или особая, питонячая магия - ХЗ.
вдогонку
 >>> a=[1,2,3]
>>> id(a)
25782232
 >>> a+=[4]
>>> id(a)
25782232
>>> a= a+ [5]
>>> id(a)
25767688
 >>>
что кагбе намекает что методы таки работают по разному. a += b изменяет список по месту. a = a + b создает новый объект.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Март 24, 2017 21:37:53)

Офлайн

#8 Март 24, 2017 21:56:20

4kpt_V
От: Харьков
Зарегистрирован: 2017-02-19
Сообщения: 299
Репутация: +  12  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

PEHDOM
Так и написано в топике, который я выше скинул. Вы правы. В одном случае происходит изменение объекта, а в другом создание нового. Но все равно поведение не очевидное и для питона это проблема. При этом мы не привыкли к неявному приведению типов. А тут такое…

Офлайн

#9 Март 25, 2017 00:33:22

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9726
Репутация: +  843  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

4kpt_V
вот тут описано почему так происходит
Там описано другое
Operator Overload, __and__, (+) and __iand__ (+=)

Both + and += operators are defined for list. They are semantically similar to extend.

my_list + another_list creates a third list in memory, so you can return the result of it, but it requires that the second iterable be a list.

my_list += another_list modifies the list in-place (it is the in-place operator, and lists are mutable objects, as we've seen) so it does not create a new list. It also works like extend, in that the second iterable can be any kind of iterable.

То есть он пишет только про списки. А то, что он пишет, что оно может быть любым итераблом в случае +=, ну, так он описал просто поведение этого бага. Это же не документация, иначе должно быть логическое обоснование, почему + не работает так же, а в документации на этот счёт ничего нет.

На списках оно работает.
lst = lst + [1, 2] - работает
lst += [1, 2] - работает

А на строках (кортежах и других итерабельных типах) не работает.
lst = lst + 'abc' - не работает
lst += 'abc' - работает
Либо операция + должна и со строками работать, либо операция += не должна со строками работать.

Это ошибка ядра питона. И, судя по поведению bytearray(), оно не должно работать со строками, потому что list() и bytarray() считаются подобными мутабельными типами.

Вот ещё итерабельный тип.
  
>>> lst = [1, 2, 3]
>>> 
>>> lst + range(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "range") to list
>>> 
>>> lst += range(3)
>>> 
>>> lst
[1, 2, 3, 0, 1, 2]
>>>
Если он пишет, что не может сконкатенировать их, то и в составном присваивании, где также используется конкатенация, он не должен мочь этого. Если же он может так конкатенировать, то должен мочь везде. И bytearray() должен иметь такое же поведение, потому что эти типы устроены одинаково.



Отредактировано py.user.next (Март 25, 2017 00:47:31)

Офлайн

#10 Март 25, 2017 08:26:01

4kpt_V
От: Харьков
Зарегистрирован: 2017-02-19
Сообщения: 299
Репутация: +  12  -
Профиль   Отправить e-mail  

Конкатенация кортежа к списку

Да там просто вопрос был по list, поэтому человек и ответил про list. Был бы вопрос по tuple был бы тот же ответ. Это не бага. Это просто такая возможность. Типа как в последнем пайтоне словари, которые хранят последовательность. Просто возможность неявная, но это уже другое дело. Ну и все в документации написать не получиться никогда.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version