0

I just started learning OOP in Python and came across interesting problem. In short, it's about running a method in the same line as object is initialised - the proposed solution was to return object after each method which we need to "oneline" that way.

My question is, is there a way to create decorator which will do the same thing?

So instead of defining colour() with return:

class Text:

  def __init__(self):
    self.i = 5

  def colour(self, sth):
    self.i = sth
    return self

The method would look like that:

  @Returning(self)
  def colour(self, sth):
    self.i = sth

This way of doing that is not only a bit more aesthetically pleasing for me, but it easily informs anyone reading the code about method being able to be one-liner, which I find important.
The issue is, though, that trying to come up with my own poor knowledge on decorators, self parameter wasn't even recognised when passed into it.

6
  • 5
    FYI, the term for this programming style is "fluent programming". It's generally considered unpythonic. Commented Nov 5, 2022 at 20:15
  • The argument for the decorator is evaluated when defining the function, it can't refer to variables in the function being decorated. But since self is always the first argument, you can write a decorator that always returns the first argument. Commented Nov 5, 2022 at 20:16
  • @Barmar Thank you so much, it worked! Such a shame it's not a main response, I would put it as resolving one. Commented Nov 5, 2022 at 20:25
  • It's not really an answer, just pointing you in the right direction. You can post your actual code as an answer. Commented Nov 5, 2022 at 20:42
  • 1
    I'm not sure why you think this is more pleasing. The new code is no shorter than the old, but now you're obscuring what it does. Why do you think it's important that colour is otherwise a one-liner? Nobody calling the method will care. Commented Nov 5, 2022 at 21:16

1 Answer 1

0

Thanks to @Barmar pointing out that self is always first argument passed to function (hence, also decorator), I was able to come up with properly working decorator code:

def Returning(func):

    @functools.wraps(func)
    def wrapper_func(*args, **kwargs):
        func(*args, **kwargs)
        return args[0]

    return wrapper_func

So the class/run code can look like this:

class Text:

  def __init__(self):
    self.i = 5

  @Returning
  def colour(self, sth):
    self.i = sth

i = Text().colour(25)

Thank you!

Sign up to request clarification or add additional context in comments.

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.