Overriding "+=" in Python? (_Iadd_() Method)

Overriding += in Python? (__iadd__() method)

Yes, override the __iadd__ method. Example:

def __iadd__(self, other):
self.number += other.number
return self

TypeError after overriding the __add__ method

You need to define __radd__ as well to get this to work.

__radd__ is reverse add. When Python tries to evaluate x + y it first attempts to call x.__add__(y). If this fails then it falls back to y.__radd__(x).

This allows you to override addition by only touching one class. Consider for example how Python would have to evaluate 0 + x. A call to 0.__add__(x) is attempted but int knows nothing about your class. You can't very well change the __add__ method in int, hence the need for __radd__. I suppose it is a form of dependency inversion.

As Steven pointed out, sum operates in place, but starts from 0. So the very first addition is the only one that would need to use __radd__. As a nice exercise you could check that this was the case!

Overriding __iadd__ in python for fractions

  • Use __iadd__ to increment in-place.
  • Use __add__ to increment and create a new instance.

So, you can change your code as follow.

def __iadd__(self, other):
self.num = self.num * other.den + self.den * other.num
self.den = self.den * other.den
return self

See also this question: implementing add and iadd for custom class in python?

Note that Python has a Rational numbers module. Check the source code… But Fraction objects are immutable, so __iadd__ is not implemented.

Overriding special methods on an instance

Python usually doesn't call the special methods (those with name surrounded by __) on the instance, but only on the class. (Although this is an implementation detail, it's characteristic of CPython, the standard interpreter.) So there's no way to override __repr__() directly on an instance and make it work. Instead, you need to do something like so:

class A(object):
def __repr__(self):
return self._repr()
def _repr(self):
return object.__repr__(self)

Now you can override __repr__() on an instance by substituting _repr().

Understanding Python super() with __init__() methods

super() lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven't already.

Note that the syntax changed in Python 3.0: you can just say super().__init__() instead of super(ChildB, self).__init__() which IMO is quite a bit nicer. The standard docs also refer to a guide to using super() which is quite explanatory.

Odoo 14 overriding method

The problem is that you are not extending the sale.order model, but creating a new one (saleoverride.saleoverride) based on sale.order.

Check odoo docs: Inheritance and extension

from odoo import models, fields, api
import logging
_logger = logging.getLogger(__name__)

class saleoverride(models.Model):
_description = 'saleoverride'
_inherit = 'sale.order'

name = fields.Char()
# value = fields.Integer()
# value2 = fields.Float(compute="_value_pc", store=True)
description = fields.Text()

transaction_ids = fields.Many2many('payment.transaction', 'saleoverride_transaction_rel', 'saleoverride_id', 'transaction_id',
string='Transactions', copy=False, readonly=True)
tag_ids = fields.Many2many('crm.tag', 'saleoverride_tag_rel', 'saleoverride_id', 'tag_id', string='Tags')

def action_confirm(self):
res = super(SaleOrder, self).action_confirm()
_logger.info("saleoverride_action_confirm")
_logger.info(self)
return res

Removing _name = 'saleoverride.saleoverride' from your class adds new features to sale.order.

Also remove the decorator since the original function doesn't have one.

How to override a magic method for the current script without a class?

__setattr__ only applies to assignments of the form a.b = c, which translates to type(a).__setattr__(b, c). Simple name assignments are a fundamental operation of the language itself, not implemented by any magic method.

You are just defining a module level function named __setattr__, not a magic method of any particular class.

Calling class staticmethod within the class body?

staticmethod objects apparently have a __func__ attribute storing the original raw function (makes sense that they had to). So this will work:

class Klass(object):

@staticmethod # use as decorator
def stat_func():
return 42

_ANS = stat_func.__func__() # call the staticmethod

def method(self):
ret = Klass.stat_func()
return ret

As an aside, though I suspected that a staticmethod object had some sort of attribute storing the original function, I had no idea of the specifics. In the spirit of teaching someone to fish rather than giving them a fish, this is what I did to investigate and find that out (a C&P from my Python session):

>>> class Foo(object):
... @staticmethod
... def foo():
... return 3
... global z
... z = foo

>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>

Similar sorts of digging in an interactive session (dir is very helpful) can often solve these sorts of question very quickly.

What does SyntaxError: Missing parentheses in call to 'print' mean in Python?

This error message means that you are attempting to use Python 3 to follow an example or run a program that uses the Python 2 print statement:

print "Hello, World!"

The statement above does not work in Python 3. In Python 3 you need to add parentheses around the value to be printed:

print("Hello, World!")

“SyntaxError: Missing parentheses in call to 'print'” is a new error message that was added in Python 3.4.2 primarily to help users that are trying to follow a Python 2 tutorial while running Python 3.

In Python 3, printing values changed from being a distinct statement to being an ordinary function call, so it now needs parentheses:

>>> print("Hello, World!")
Hello, World!

In earlier versions of Python 3, the interpreter just reports a generic syntax error, without providing any useful hints as to what might be going wrong:

>>> print "Hello, World!"
File "<stdin>", line 1
print "Hello, World!"
^
SyntaxError: invalid syntax

As for why print became an ordinary function in Python 3, that didn't relate to the basic form of the statement, but rather to how you did more complicated things like printing multiple items to stderr with a trailing space rather than ending the line.

In Python 2:

>>> import sys
>>> print >> sys.stderr, 1, 2, 3,; print >> sys.stderr, 4, 5, 6
1 2 3 4 5 6

In Python 3:

>>> import sys
>>> print(1, 2, 3, file=sys.stderr, end=" "); print(4, 5, 6, file=sys.stderr)
1 2 3 4 5 6

Starting with the Python 3.6.3 release in September 2017, some error messages related to the Python 2.x print syntax have been updated to recommend their Python 3.x counterparts:

>>> print "Hello!"
File "<stdin>", line 1
print "Hello!"
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Hello!")?

Since the "Missing parentheses in call to print" case is a compile time syntax error and hence has access to the raw source code, it's able to include the full text on the rest of the line in the suggested replacement. However, it doesn't currently try to work out the appropriate quotes to place around that expression (that's not impossible, just sufficiently complicated that it hasn't been done).

The TypeError raised for the right shift operator has also been customised:

>>> print >> sys.stderr
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'builtin_function_or_method' and '_io.TextIOWrapper'. Did you mean "print(<message>, file=<output_stream>)"?

Since this error is raised when the code runs, rather than when it is compiled, it doesn't have access to the raw source code, and hence uses meta-variables (<message> and <output_stream>) in the suggested replacement expression instead of whatever the user actually typed. Unlike the syntax error case, it's straightforward to place quotes around the Python expression in the custom right shift error message.



Related Topics



Leave a reply



Submit