overload builtin operator

Bengt Richter bokr at oz.net
Fri Aug 26 17:21:19 EDT 2005


On Thu, 25 Aug 2005 16:12:20 +0200, Reinhold Birkenfeld <reinhold-birkenfeld-nospam at wolke7.net> wrote:

>Shaun wrote:
>> Hi,
>> 
>> I'm trying to overload the divide operator in python for basic arithmetic.
>> eg. 10/2 ... no classes involved.
>> 
>> I am attempting to redefine operator.__div__ as follows:
>> 
>>      # my divide function
>>      def safediv(a,b):
>>          return ...
>> 
>>      # reassign buildin __div__
>>      import operator
>>      operator.__div__ = safediv
>> 
>> The operator.__dict__ seems to be updated OK but the '/' operator still  
>> calls buildin __div__
>
>It won't work that way. You cannot globally modify the behaviour of an operator,
>but you can customize how an operator works for your type.
>
>Consider:
>
>class safeint(int):
>    def __div__(self, other):
>        return safediv(self, other)
>
>safeint(10)/2
>
You are right that you cannot globally modify the behaviour of an operator in the
sense the OP seems to be envisioning, but with some trouble I think it would be possible
to interfere with the translation of '<numerator-term>/<denominator-term>' to become
'safediv(<numerator-term>, <denominator-term>)' by transforming the AST during a custom
import process, such that wherever a Div node is found, a CallFunc node is substituted. E.g.,

for a node like

    Div((Name('numerator'), Name('denominator')))

substitute another node like

    CallFunc(Name('safediv'), [Name('numerator'), Name('denominator')], None, None)

where the Name('numerator') and Name('denominator') in the latter are actually
the Div node's .left and .right, so as to operate on the same args (which can
be abitrary expression-representing subtrees).

Of course, you probably also want to replace

    AugAssign(Name('a'), '/=', Name('b'))

with

    Assign([AssName('a', 'OP_ASSIGN')], CallFunc(Name('safediv'), [Name('a'), Name('b')], None, None))

Unfortunately, the AST tree does not seem to be designed to be edited easily wrt
_replacing_ nodes found by walking via flattened lists vs. just _using_ them in order.

I think I can create special walker that can do replacements of nodes found anywhere, and
calling node-type-specific or default supplied callbacks to supply replacements for original nodes
passed to them, but this will require a number of specialized visitors etc., so I will have to get back
to this later. But at least the OP and you nudged me into thinking about AST rewriting again ;-)
(also affects my @@sourcedeco ideas ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list