22

I want to have a class that I can create subclasses of that has a print function that only prints on a particular condition.

Here's basically what I'm trying to do:

class ClassWithPrintFunctionAndReallyBadName:
    ...
    def print(self, *args):
        if self.condition:
            print(*args)

This works already except for the fact that there are arguments that have to be explicitly stated with the default print function, such as end (example: print('Hello, world!', end='')). How can I make my new class's print function accept arguments such as end='' and pass them to the default print?

1
  • 3
    you could use **kwargs Commented Feb 28, 2017 at 3:31

5 Answers 5

41

The standard way to pass on all arguments is as @JohnColeman suggested in a comment:

class ClassWithPrintFunctionAndReallyBadName:
    ...
    def print(self, *args, **kwargs):
        if self.condition:
            print(*args, **kwargs)

As parameters, *args receives a tuple of the non-keyword (positional) arguments, and **kwargs is a dictionary of the keyword arguments.

When calling a function with * and **, the former tuple is expanded as if the parameters were passed separately and the latter dictionary is expanded as if they were keyword parameters.

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

Comments

15

I know it looks a bit ugly but works perfectly, if you are using a lot of keyword arguments and only want to build a facade for another method:

def print(self, print_message, end='\n', sep=' ', flush=False, file=None):
    if self.condition:
        print(**{key: value for key, value in locals().items() if key != 'self'})

Although it's a lot of boilerplate, it avoids any duplication of parameter statements.

You might also look into using a decorator to make the conditional part more pythonic. But beware that the decorator checks the condition once prior to the class instantiation.

1 Comment

Yes, you are right. I overlooked this. Probably had a tuple with more input there, when writing the code in production.
4

Just duplicate the named arguments for the method signature.

def print(self, *args, end='\n', sep=' ', flush=False, file=None):
    if self.condition:
        print(*args, end=end, sep=sep, flush=flush, file=file)

4 Comments

If someone would tell me what's wrong with this answer to make it deserve a downvote, I would love to fix the issues.
Your answer is fine for the problem at hand. It is hard to figure out downvotes at times.
struck by the random disliker :< I feel like if you dislike something you must make a comment if there are none, otherwise it's as unhelpful as 'my code doesn't work' questions
@TigerhawkT3, compared to the args and kargs solution your anwser is not generalizable. So it is better to show it to the users after those ones. That may be the reason of downvotes.
2
class List(list):
    def append_twice(self, *args, **kwargs):
        self.append(*args, **kwargs)
        self.append(*args, **kwargs)
l = List()
l.append_twice("Hello")
print(l) # ['Hello', 'Hello']

Comments

1

Add at the end like this

def print(self, *args, end=''):

If the arguments are dynamic or too many:

 def print(self, *args, **kwargs):

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.