[Python-Dev] summing integer and class
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
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
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
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
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
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