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 890253
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T13:42:09+00:00 2026-05-15T13:42:09+00:00

I’d like to implement an object, that bounds values within a given range after

  • 0

I’d like to implement an object, that bounds values within a given range after arithmetic operations have been applied to it. The code below works fine, but I’m pointlessly rewriting the methods. Surely there’s a more elegant way of doing this. Is a metaclass the way to go?

def check_range(_operator):
    def decorator1(instance,_val):
        value =  _operator(instance,_val)
        if value > instance._upperbound:
            value = instance._upperbound
        if value < instance._lowerbound:
            value = instance._lowerbound
        instance.value = value
        return Range(value, instance._lowerbound, instance._upperbound)
    return decorator1

class Range(object):
    '''
    however you add, multiply or divide, it will always stay within boundaries
    '''
    def __init__(self, value, lowerbound, upperbound):
        '''

        @param lowerbound:
        @param upperbound:
        '''
        self._lowerbound = lowerbound
        self._upperbound = upperbound
        self.value = value

    def init(self):
        '''
        set a random value within bounds
        '''
        self.value = random.uniform(self._lowerbound, self._upperbound)

    def __str__(self):
        return self.__repr__()

    def __repr__(self):
        return "<Range: %s>" % (self.value)

    @check_range
    def __mul__(self, other):
        return self.value * other

    @check_range
    def __div__(self, other):
        return self.value / float(other)

    def __truediv__(self, other):
        return self.div(other)     

    @check_range
    def __add__(self, other):
        return self.value + other

    @check_range
    def __sub__(self, other):
        return self.value - other
  • 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-15T13:42:10+00:00Added an answer on May 15, 2026 at 1:42 pm

    It is possible to use a metaclass to apply a decorator to a set of function names, but I don’t think that this is the way to go in your case. Applying the decorator in the class body on a function-by-function basis as you’ve done, with the @decorator syntax, I think is a very good option. (I think you’ve got a bug in your decorator, BTW: you probably do not want to set instance.value to anything; arithmetic operators usually don’t mutate their operands).

    Another approach I might use in your situation, kind of avoiding decorators all together, is to do something like this:

    import operator
    
    class Range(object):
    
        def __init__(self, value, lowerbound, upperbound):
            self._lowerbound = lowerbound
            self._upperbound = upperbound
            self.value = value
    
        def __repr__(self):
            return "<Range: %s>" % (self.value)
    
        def _from_value(self, val):
            val = max(min(val, self._upperbound), self._lowerbound)
            # NOTE: it's nice to use type(self) instead of writing the class
            # name explicitly; it then continues to work if you change the
            # class name, or use a subclass
            return type(self)(val, rng._lowerbound, rng._upperbound)
    
        def _make_binary_method(fn):
            # this is NOT a method, just a helper function that is used
            # while the class body is being evaluated
            def bin_op(self, other):
                return self._from_value(fn(self.value, other))
            return bin_op
    
        __mul__ = _make_binary_method(operator.mul)
        __div__ = _make_binary_method(operator.truediv)
        __truediv__ = __div__
        __add__ = _make_binary_method(operator.add)
        __sub__ = _make_binary_method(operator.sub)
    
    rng = Range(7, 0, 10)
    print rng + 5
    print rng * 50
    print rng - 10
    print rng / 100
    

    printing

    <Range: 10>
    <Range: 10>
    <Range: 0>
    <Range: 0.07>
    

    I suggest that you do NOT use a metaclass in this circumstance, but here is one way you could. Metaclasses are a useful tool, and if you’re interested, it’s nice to understand how to use them for when you really need them.

    def check_range(fn):
        def wrapper(self, other):
            value = fn(self, other)
            value = max(min(value, self._upperbound), self._lowerbound)
            return type(self)(value, self._lowerbound, self._upperbound)
        return wrapper
    
    class ApplyDecoratorsType(type):
        def __init__(cls, name, bases, attrs):
            for decorator, names in attrs.get('_auto_decorate', ()):
                for name in names:
                    fn = attrs.get(name, None)
                    if fn is not None:
                        setattr(cls, name, decorator(fn))
    
    class Range(object):
        __metaclass__ = ApplyDecoratorsType
        _auto_decorate = (
                (check_range, 
                 '__mul__ __div__ __truediv__ __add__ __sub__'.split()),
            )
    
        def __init__(self, value, lowerbound, upperbound):
            self._lowerbound = lowerbound
            self._upperbound = upperbound
            self.value = value
    
        def __repr__(self):
            return "<Range: %s>" % (self.value)
    
        def __mul__(self, other):
            return self.value * other
    
        def __div__(self, other):
            return self.value / float(other)
    
        def __truediv__(self, other):
            return self / other
    
        def __add__(self, other):
            return self.value + other
    
        def __sub__(self, other):
            return self.value - other
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 449k
  • Answers 449k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer They aren't tutorials like TryRuby, but you can use ideone.com… May 15, 2026 at 8:04 pm
  • Editorial Team
    Editorial Team added an answer Can you do something like.. if ( !$(this).data('writing') ) {… May 15, 2026 at 8:04 pm
  • Editorial Team
    Editorial Team added an answer move_uploaded_file() will also return false if it can't write to… May 15, 2026 at 8:04 pm

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

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.