0

I've started to build my class in this fashion (more like a regular function):

ex 1

  class Child(Parent):

    def __init__(self,user):
        Parent.__init__(self, user)     

        search = api.search() 
        filter = api.filter(search)
        output = api.output(filter)

        return output

this way I could run:

movies = Child('John')

and get my final output.

Then, I broke my global api methods into instance methods in order to have more control of data:

ex 2

  class Child(Parent):

    def __init__(self,user):
        Parent.__init__(self, user)     

    def search_api(self):
       search = api.search() 
       return search    

    def filter_api(self, search):
       filter = api.filter(search)
       return filter

    def output(self, filter):
       output = api.output(filter)  
       return output

and now I have to break it in different instances, to get the final output:

test = Child('John')
search = test.search_api()
filter = test.filter_api(search)
out = test.output(filter)

print (out)

Is there a decorator or built-in method that allows me to chain all instance methods so that ex2 can be run in one shot (instantiation)?

6
  • You mean test.output(test.filter_api(test.search_api()))? Commented Jan 3, 2017 at 19:07
  • How come in ex2 you aren't using the arguments in your methods? I can't imagine it would do what you wanted in that case. Commented Jan 3, 2017 at 19:07
  • This makes no sense. Your __init__ is superfluous because it does nothing more than the superclass' does, and none of the methods ever use self, so they could just as well be perfectly normal functions. Commented Jan 3, 2017 at 19:08
  • And besides never using any of arguments of the methods, your original example tried returning something from __init__ - that doesn't work either. Commented Jan 3, 2017 at 19:10
  • @RandomDavis I am. I've edited it now, sorry. Commented Jan 3, 2017 at 19:10

4 Answers 4

2

I think what you are after is the builder pattern so you could write output = Search().filter().get_output() or something like that.

For this to work, you need to return the builder object from all the "intermediate" methods:

class Search(object):
    def __init__(self, *args, **kwargs):
        # apply args, kwargs

    def filter(self, *args, **kwargs):
        # apply args, kwargs
        self.filters.append(...)
        return self

    def paginate(self, *args, **kwargs):
        # apply args, kwargs
        self.pagination = ...
        return self

    def get_output(self, *args, **kwargs):
        # apply args, kwargs
        # build the search, find output ...
        return output
Sign up to request clarification or add additional context in comments.

Comments

1

No need for the magic stuff if you need to make objects behave like function calls you should implement __call__ instead of just packing everything in the constructor.:

class Child(Parent):

    def __init__(self,user):
        Parent.__init__(self, user)
        self.myuser = user


    def search_api(self):
       search = api.search() 
       return search    

    def filter_api(self, search):
       filter = api.filter()
       return filter

    def output(self, filter): 
       return output

    def __call__(self,user):
        search = self.search_api()
        filter = self.filter_api(search)
        return self.output(filter)

And now you can:

a = Child('Joe')
print(a())

3 Comments

You'll get TypeError: __init__() should return None
Yep, that's what I get for posting without reviewing my answers, edited the answer. Thanks @RencoGerlich
all answers were valid, but I think this is the simplest.
1

Some helpers to make it compile:

class API:
    def __getattr__(self, attr):
        return API()
    def __call__(self, x=1):
        return 42

api = API()

class Parent(object):
     def __init__(self, user):
        self.user = user

Doing all steps in process method:

class Child(Parent):

    def __init__(self, user):
        super().__init__(user)     

    def search_api(self):
        search = api.search() 
        return search    

    def filter_api(self, search):
        filter = api.filter()
        return filter

    def output(self, filter):   
        return api.output

    def process(self):
        res = self.search_api() 
        res = self.filter_api(res)
        return self.output(res)

allows you to do all in one line:

movies = Child('John').process()

Comments

1

You can use __call__(). I know it's not the same, but perhaps it might be better than your ex2:

class Child(Parent):

    def __init__(self, user):
        Parent.__init__(self, user)

    def search_api(self):
        search = api.search() 
        return search    

    def filter_api(self, search):
        filter = api.filter(search)
        return filter

    def output(self, filter):
        output = api.output(filter)  
        return output

    def __call__(self):
        search = self.search_api()
        filter = self.filter_api(search)
        return self.output(filter)

Then, you can do:

c = Child("john")
output = c()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.