[Python-Dev] summing integer and class

2013-10-03 Thread Igor Vasilyev

Hi.

Example test.py:

class A():
def __add__(self, var):
print(I'm in A class)
return 5
a = A()
a+1
1+a

Execution:
python test.py
I'm in A class
Traceback (most recent call last):
  File ../../test.py, line 7, in module
1+a
TypeError: unsupported operand type(s) for +: 'int' and 'instance'


So adding integer to class works fine, but adding class to integer fails.
I could not understand why it happens. In objects/abstact.c we have the 
following function:


static PyObject *
binary_op1(PyObject *v, PyObject *w, const int op_slot)
{
PyObject *x;
binaryfunc slotv = NULL;
binaryfunc slotw = NULL;

if (v-ob_type-tp_as_number != NULL)
slotv = NB_BINOP(v-ob_type-tp_as_number, op_slot);
if (w-ob_type != v-ob_type 
w-ob_type-tp_as_number != NULL) {
slotw = NB_BINOP(w-ob_type-tp_as_number, op_slot);
if (slotw == slotv)
slotw = NULL;
}
if (slotv) {
if (slotw  PyType_IsSubtype(w-ob_type, v-ob_type)) {
x = slotw(v, w);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
slotw = NULL;
}
x = slotv(v, w);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
if (slotw) {
x = slotw(v, w);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
Py_RETURN_NOTIMPLEMENTED;
}

When we adding class to integer we have both slotv and slotw. x = 
slotv(v, w); - returns Py_NotImplemented.
But in this case we should execute x = slotw(v, w); and function should 
be completed in the same way as when we adding integer to class.


Can someone advise please where I mistake.

--
thanks,
Igor Vasilyev
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] summing integer and class

2013-10-03 Thread Игорь Васильев
 Hi.


Example test.py:

class A():
    def __add__(self, var):
    print(I'm in A class)
    return 5
a = A()
a+1
1+a

Execution:
python test.py
I'm in A class
Traceback (most recent call last):
  File ../../test.py, line 7, in module
    1+a
TypeError: unsupported operand type(s) for +: 'int' and 'instance'


So adding integer to class works fine, but adding class to integer fails.
I could not understand why it happens. In objects/abstact.c we have the 
following function:

static PyObject *
binary_op1(PyObject *v, PyObject *w, const int op_slot)
{
    PyObject *x;
    binaryfunc slotv = NULL;
    binaryfunc slotw = NULL;

    if (v-ob_type-tp_as_number != NULL)
    slotv = NB_BINOP(v-ob_type-tp_as_number, op_slot);
    if (w-ob_type != v-ob_type 
    w-ob_type-tp_as_number != NULL) {
    slotw = NB_BINOP(w-ob_type-tp_as_number, op_slot);
    if (slotw == slotv)
    slotw = NULL;
    }
    if (slotv) {
    if (slotw  PyType_IsSubtype(w-ob_type, v-ob_type)) {
    x = slotw(v, w);
    if (x != Py_NotImplemented)
    return x;
    Py_DECREF(x); /* can't do it */
    slotw = NULL;
    }
    x = slotv(v, w);
    if (x != Py_NotImplemented)
    return x;
    Py_DECREF(x); /* can't do it */
    }
    if (slotw) {
    x = slotw(v, w);
    if (x != Py_NotImplemented)
    return x;
    Py_DECREF(x); /* can't do it */
    }
    Py_RETURN_NOTIMPLEMENTED;
}

When we adding class to integer we have both slotv and slotw. x = slotv(v, w); 
- returns Py_NotImplemented.
But in this case we should execute x = slotw(v, w); and function should be 
completed in the same way as when we adding integer to class. 

Can someone advise please where I mistake. 

-- 
thanks,
Igor Vasilyev
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] summing integer and class

2013-10-03 Thread Chris Angelico
On Thu, Oct 3, 2013 at 11:09 PM, Игорь Васильев vasilyev_i...@inbox.ru wrote:
 When we adding class to integer we have both slotv and slotw. x = slotv(v,
 w); - returns Py_NotImplemented.
 But in this case we should execute x = slotw(v, w); and function should be
 completed in the same way as when we adding integer to class.

 Can someone advise please where I mistake.

No need to dig into the CPython source for this, the answer's pretty
simple: 1+a is handled by __radd__ not __add__.

 class A():
def __add__(self, var):
print(I'm in A class)
return 5
def __radd__(self, var):
print(I'm in A class, too)
return 6

 a=A()
 a+1
I'm in A class
5
 1+a
I'm in A class, too
6

You could ask this sort of thing on python-l...@python.org rather than
python-dev.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] summing integer and class

2013-10-03 Thread Xavier Morel

On 2013-10-03, at 15:45 , Igor Vasilyev wrote:

 Hi.
 
 Example test.py:
 
 class A():
def __add__(self, var):
print(I'm in A class)
return 5
 a = A()
 a+1
 1+a
 
 Execution:
 python test.py
 I'm in A class
 Traceback (most recent call last):
  File ../../test.py, line 7, in module
1+a
 TypeError: unsupported operand type(s) for +: 'int' and 'instance'
 
 
 So adding integer to class works fine, but adding class to integer fails.
 I could not understand why it happens. In objects/abstact.c we have the 
 following function:
 

python-dev is about developing Python itself, not about developing in
Python, so that's the wrong mailing list for these kinds of question.

But FWIW the answer is that Python first tries 1.__add__(a), when that
fails (with NotImplemented) it uses the reflected method[0] which is
a.__radd__(1). Since that does not exist, the operation is invalid.

[0] http://docs.python.org/2/reference/datamodel.html#object.__radd__
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] summing integer and class

2013-10-03 Thread Chris Kaynor
This list is for development OF Python, not for development in python. For
that reason, I will redirect this to python-list as well. My actual answer
is below.

On Thu, Oct 3, 2013 at 6:45 AM, Igor Vasilyev igor.vasil...@oracle.com
 wrote:

 Hi.

 Example test.py:

 class A():
 def __add__(self, var):
 print(I'm in A class)
 return 5
 a = A()
 a+1
 1+a


 Execution:
 python test.py
 I'm in A class
 Traceback (most recent call last):
   File ../../test.py, line 7, in module
 1+a
 TypeError: unsupported operand type(s) for +: 'int' and 'instance'


 So adding integer to class works fine, but adding class to integer fails.
 I could not understand why it happens. In objects/abstact.c we have the
 following function:


Based on the code you provided, you are only overloading the __add__
operator, which is only called when an A is added to something else, not
when something is added to an A. You can also override the __radd__
method to perform the swapped addition. See
http://docs.python.org/2/reference/datamodel.html#object.__radd__ for the
documentation (it is just below the entry on __add__).

Note that for many simple cases, you could define just a single function,
which then is defined as both the __add__ and __radd__ operator. For
example, you could modify your A sample class to look like:

class A():
def __add__(self, var):
print(I'm in A)
return 5
__radd__ = __add__


Which will produce:
 a = A()
 a + 1
I'm in A
5
 1 + a
I'm in A
5

Chris
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] summing integer and class

2013-10-03 Thread Greg Ewing

Igor Vasilyev wrote:


class A():
def __add__(self, var):
print(I'm in A class)
return 5
a = A()
a+1
1+a

Execution:
python test.py
I'm in A class
Traceback (most recent call last):
  File ../../test.py, line 7, in module
1+a
TypeError: unsupported operand type(s) for +: 'int' and 'instance'


You need to define an __radd__ method for it to work
as a right-hand operand.

When we adding class to integer we have both slotv and slotw. x = 
slotv(v, w); - returns Py_NotImplemented.

But in this case we should execute x = slotw(v, w);


Yes, but the wrapper that gets put in the type slot calls
__rxxx__ instead of __xxx__ if it's being called for the
right-hand operand.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com