Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7016107
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T22:44:28+00:00 2026-05-27T22:44:28+00:00

I have a class that need to make some magic with every operator, like

  • 0

I have a class that need to make some magic with every operator, like __add__, __sub__ and so on.

Instead of creating each function in the class, I have a metaclass which defines every operator in the operator module.

import operator
class MetaFuncBuilder(type):
    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)
        attr = '__{0}{1}__'
        for op in (x for x in dir(operator) if not x.startswith('__')):
            oper = getattr(operator, op)

            # ... I have my magic replacement functions here
            # `func` for `__operators__` and `__ioperators__`
            # and `rfunc` for `__roperators__`

            setattr(self, attr.format('', op), func)
            setattr(self, attr.format('r', op), rfunc)

The approach works fine, but I think It would be better if I generate the replacement operator only when needed.

Lookup of operators should be on the metaclass because x + 1 is done as type(x).__add__(x,1) instead of x.__add__(x,1), but it doesn’t get caught by __getattr__ nor __getattribute__ methods.

That doesn’t work:

class Meta(type):
     def __getattr__(self, name):
          if name in ['__add__', '__sub__', '__mul__', ...]:
               func = lambda:... #generate magic function
               return func

Also, the resulting “function” must be a method bound to the instance used.

Any ideas on how can I intercept this lookup? I don’t know if it’s clear what I want to do.


For those questioning why do I need to this kind of thing, check the full code here.
That’s a tool to generate functions (just for fun) that could work as replacement for lambdas.

Example:

>>> f = FuncBuilder()
>>> g = f ** 2
>>> g(10)
100
>>> g
<var [('pow', 2)]>

Just for the record, I don’t want to know another way to do the same thing (I won’t declare every single operator on the class… that will be boring and the approach I have works pretty fine :). I want to know how to intercept attribute lookup from an operator.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T22:44:29+00:00Added an answer on May 27, 2026 at 10:44 pm

    Some black magic let’s you achieve your goal:

    operators = ["add", "mul"]
    
    class OperatorHackiness(object):
      """
      Use this base class if you want your object
      to intercept __add__, __iadd__, __radd__, __mul__ etc.
      using __getattr__.
      __getattr__ will called at most _once_ during the
      lifetime of the object, as the result is cached!
      """
    
      def __init__(self):
        # create a instance-local base class which we can
        # manipulate to our needs
        self.__class__ = self.meta = type('tmp', (self.__class__,), {})
    
    
    # add operator methods dynamically, because we are damn lazy.
    # This loop is however only called once in the whole program
    # (when the module is loaded)
    def create_operator(name):
      def dynamic_operator(self, *args):
        # call getattr to allow interception
        # by user
        func = self.__getattr__(name)
        # save the result in the temporary
        # base class to avoid calling getattr twice
        setattr(self.meta, name, func)
        # use provided function to calculate result
        return func(self, *args)
      return dynamic_operator
    
    for op in operators:
      for name in ["__%s__" % op, "__r%s__" % op, "__i%s__" % op]:
        setattr(OperatorHackiness, name, create_operator(name))
    
    
    # Example user class
    class Test(OperatorHackiness):
      def __init__(self, x):
        super(Test, self).__init__()
        self.x = x
    
      def __getattr__(self, attr):
        print "__getattr__(%s)" % attr
        if attr == "__add__":
          return lambda a, b: a.x + b.x
        elif attr == "__iadd__":
          def iadd(self, other):
            self.x += other.x
            return self
          return iadd
        elif attr == "__mul__":
          return lambda a, b: a.x * b.x
        else:
          raise AttributeError
    
    ## Some test code:
    
    a = Test(3)
    b = Test(4)
    
    # let's test addition
    print(a + b) # this first call to __add__ will trigger
                # a __getattr__ call
    print(a + b) # this second call will not!
    
    # same for multiplication
    print(a * b)
    print(a * b)
    
    # inplace addition (getattr is also only called once)
    a += b
    a += b
    print(a.x) # yay!
    

    Output

    __getattr__(__add__)
    7
    7
    __getattr__(__mul__)
    12
    12
    __getattr__(__iadd__)
    11
    

    Now you can use your second code sample literally by inheriting from my OperatorHackiness base class. You even get an additional benefit: __getattr__ will only be called once per instance and operator and there is no additional layer of recursion involved for the caching. We hereby circumvent the problem of method calls being slow compared to method lookup (as Paul Hankin noticed correctly).

    NOTE: The loop to add the operator methods is only executed once in your whole program, so the preparation takes constant overhead in the range of milliseconds.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have method in a class that I need to make sure is only
I have a class that I need to perform some actions on but I
I have a class that subclasses UITableViewCell. I need to initialize some of the
I have a class that contains some private attributes. What I would like to
Suppose I have a class that looks like this: class Derived : // some
I have a class that I need to binary serialize. The class contains one
I have a class that I need to be able to serialize to a
I have a class that has a property that I need to stub. I
I have a simple Java class that I need to serialize to be stored
I have a parent and child class that both need to implement IDisposable .

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.