Why do we have callable objects in python?

后端 未结 3 657
感情败类
感情败类 2020-12-16 00:53

What is the purpose of a callable object? What problems do they solve?

相关标签:
3条回答
  • 2020-12-16 01:45

    Many kinds of objects are callable in Python, and they can serve many purposes:

    • functions are callable, and they may carry along a "closure" from an outer function
    • classes are callable, and calling a class gets you an instance of that class
    • methods are callable, for function-like behavior specifically pertaining to an instance
    • staticmethods and classmethods are callable, for method-like functionality when the functionality pertains to "a whole class" in some sense (staticmethods' usefulness is dubious, since a classmethod could do just as well;-)
    • generators are callable, and calling a generator gets you an iterator object
    • finally, and this may be specifically what you were asking about (not realizing that all of the above are objects too...!!!), you can code a class whose instances are callable: this is often the simplest way to have calls that update an instance's state as well as depend on it (though a function with a suitable closure, and a bound method, offer alternatives, a callable instance is the one way to go when you need to perform both calling and some other specific operation on the same object: for example, an object you want to be able to call but also apply indexing to had better be an instance of a class that's both callable and indexable;-).

    A great range of examples of the kind of "problems they solve" is offered by Python's standard library, which has many cases of each of the specific types I mention above.

    0 讨论(0)
  • 2020-12-16 01:46

    They take parameters and return a result depending on those parameters.

    A callable is just an abstract form of a function resp an interface that defines that an object acts like a function (i.e. accepts parameters).

    As functions are first class objects, it is obvious that functions are callable objects. If you are talking about the __call__ method, this is just one of the many special methods with which you can overload the behavior of custom objects, e.g. for arithmetic operations or also defining what happens if you call an object.

    One idea why to use such is to have some kind of factory object that itself creates other objects.

    0 讨论(0)
  • 2020-12-16 01:49

    There are areas, especially in the 'functions calling functions of function functions' where objects allow less nesting.

    Consider making a classic decorator that checks an authorization level before calling a function. Using it is clear:

    @check_authorization(level="Manager")
    def update_price(Item, new_price):...
    

    You could do this as nested functions:

    def check_authorization(level):
         def take_params(function):
             def concrete(*args, **kwargs):
                 if user_level_greater_than(level):
                     return function(*args, 
                         **kwargs)
                 return None
             return concrete
         return take_params
    

    Or you could to this as a class, which might be clearer:

      class check_authorization(object):
          def __init__(level):
             self.level = level
          def __call__(function):
              self.function = function
              return self.dec
          def dec(self, *args, **kwargs):
              if user_level_greater_than(self.level):
                 return self.function(*args,v**kwargs)
              return None
    

    Many would find this flat method more clear. Of course, I believe in cheating, because I like the signatures and metadata correct:

    from dectools.dectools import make_call_if
    
    @make_call_if
    def check_authorization(function, arg, kwargs, level):
        return user_level_greater_than(level)
    

    The callable object is a tool which is good for some known applications and may also be good for the bizarre problem real life throws at you.

    0 讨论(0)
提交回复
热议问题