Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 21, 2016 20:51:37

DenLadon
Зарегистрирован: 2016-06-27
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

перегрузка операторов

Привет.
Помогите разобраться с кодом.

class Number:
def __init__(self, val):
self.val = val
def __iadd__(self, other):
self.val += other
return self
Почему возвращается self а не self.val?
Не пойму в чем механика

Офлайн

#2 Окт. 21, 2016 21:35:20

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

перегрузка операторов

DenLadon
Почему возвращается self а не self.val?
Не пойму в чем механика
 a="asd"
b=a
a+="123"
print(a)
print(b)
>>> asd123
>>> asd
В результате += в a записывается адрес объекта возвращаемого оператором +=



Отредактировано doza_and (Окт. 21, 2016 21:42:19)

Офлайн

#3 Окт. 21, 2016 22:01:56

DenLadon
Зарегистрирован: 2016-06-27
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

перегрузка операторов

Наверно вопрос мой не совсем корректен.
В случае:

 class Number1:
	def __init__(self, val):
		self.val = val
	def __iadd__(self, other):
		self.val += other
		return self
Получается следующее:
 >>> a = Number1(5)
>>> a += 1
>>> a
6
>>> a.val
Traceback (most recent call last):
  File "<pyshell#55>", line 1, in <module>
    a.val
AttributeError: 'int' object has no attribute 'val'
а если сделать:
 class Number2:
	def __init__(self, val):
		self.val = val
	def __iadd__(self, other):
		self.val += other
		return self
Тогда будет:
 b = Number2(5)
>>> b += 1
>>> b
<__main__.Number object at 0x000001A6B4E875F8>
>>> b.val
6
Не понятно почему а, изначально определена как экземпляр класса становиться обычным числом.

Отредактировано DenLadon (Окт. 21, 2016 22:08:10)

Офлайн

#4 Окт. 22, 2016 02:56:55

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

перегрузка операторов

python.org. __iadd__

These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self).

DenLadon
Получается следующее:
  
 >>> a = Number1(5)
>>> a += 1
>>> a
6
>>> a.val
Traceback (most recent call last):
  File "<pyshell#55>", line 1, in <module>
    a.val
AttributeError: 'int' object has no attribute 'val'

Где оно получается, всё нормально там
  
>>> class Number1:
...     def __init__(self, val):
...         self.val = val
...     def __iadd__(self, other):
...         self.val += other
...         return self
... 
>>> a = Number1(5)
>>> a += 1
>>> a
<__main__.Number1 object at 0xb739a50c>
>>> a.val
6
>>>

Добавишь __repr__ - будет число выводить
  
>>> class Number1:
...     def __init__(self, val):
...         self.val = val
...     def __iadd__(self, other):
...         self.val += other
...         return self
...     def __repr__(self):
...         return str(self.val)
... 
>>> a = Number1(5)
>>> a += 1
>>> a
6
>>> a.val
6
>>>

DenLadon
Не понятно почему а, изначально определена как экземпляр класса становиться обычным числом.
Ты просто результаты не того кода смотришь. Если возвращаешь self.val, то там лежит обычное число, у которого нет атрибута val. Если возвращаешь self, то там лежит этот объект, у которого есть атрибут val.
В питоне разницы нет, что там возвращать, так как результат присваивания (простого или составного) всё равно нельзя использовать. Это сделано специально, так как в C были частыми ошибки вроде записи = вместо ==, таким образом из-за опечатки могли быть тихие баги.



Отредактировано py.user.next (Окт. 22, 2016 03:03:54)

Офлайн

#5 Окт. 22, 2016 09:15:19

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

перегрузка операторов

py.user.next
В питоне разницы нет, что там возвращать
Это утверждение очевидно неверно.

 class Number1:
    def __init__(self, val):
        self.val = val
    def __iadd__(self, other):
        self.val += other
        return self
a = Number1(1)
a += 1
print(a)
>>> <__main__.Number1 object at 0x0000002404762208>
class Number1:
    def __init__(self, val):
        self.val = val
    def __iadd__(self, other):
        self.val += other
        return self.val
a = Number1(1)
a += 1
print(a)
>>> 2



Отредактировано doza_and (Окт. 22, 2016 09:16:16)

Офлайн

#6 Окт. 22, 2016 10:42:29

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

перегрузка операторов

doza_and
Это утверждение очевидно неверно.
Для внутренних нужд используется возвращаемое значение. Сама операция нужна, чтобы поменять объект, и никак не должна его терять. Но бывают случаи, когда объект проще создать заново с нужными изменениями, чем менять существующий.

А вот в C++ ты можешь вернуть именно число какое-то для дальнейшего использования в операциях без потери объекта.
Пример, который в питоне не сделаешь:
#include <iostream>

using namespace std;

class A {
int n;
public:
A() : n(0) {}
float operator +=(int v) { n += v * 10; return 2.7; }
void print() { cout << n << endl; }
};

int main()
{
A n;

n.print();
cout << ((n += 2) + (n += 3)) << endl;
n.print();

return 0;
}

[guest@localhost cpp]$ .iso++ t.cpp -o t; ./t
0
5.4
50
[guest@localhost cpp]$



Отредактировано py.user.next (Окт. 22, 2016 10:58:56)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version