1

I've written the following code:

class User:
    def __init__(self, first_name, last_name, gender, location):
        self.first_name = first_name
        self.last_name = last_name
        self.gender = gender
        self.location = location
        
    def describe_user(self):
        print(f"User {self.first_name} {self.last_name} is a " 
              f"{self.gender} from {self.location}")
        
    def greet_user(self):
        print(f"Hello there {self.first_name}, you come from the "
              f"{self.last_name} family. You currently reside in "
              f"{self.location}. Oh, I forgot to mention that you're "
              f"a {self.gender}. Have a nice day!")

This works, but I don't think it looks very clean.

The way I initially tried to accomplish this, which seemed most natural to me was like this:

def describe_user(self):
    print(f"User {self.first_name} {self.last_name} is a 
          {self.gender} from {self.location}")

But unfortunately that didn't work. Is there a better way to do this?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • First snippet is how some IDE such as PyCharm format your code when you type `Enter` while writing a string. To me, that's the most clean (and clear) way to write multiple lines – Buzz Aug 20 '22 at 18:45
  • 1
    What part of it doesn't look "clean" to you? The only thing I'd change might be to add a linebreak after the opening `(` and before the closing `)` so that the closing `(` is aligned with the `print` and the strings are one standard level of indentation underneath it. – Samwise Aug 20 '22 at 18:51
  • What you're doing is right. Some languages like Ruby have something called 'heredoc syntax' which allows multi-line strings with good indentation and custom linefeed behavior, but Python doesn't have any equivalent. – Silvio Mayolo Aug 20 '22 at 18:51
  • Looks fab. Don't let the perfect be the enemy of the good. – John Aug 20 '22 at 18:52
  • 2
    Does this answer your question? [Multiline f-string in Python](https://stackoverflow.com/questions/45965007/multiline-f-string-in-python) – Harsh Gupta Aug 20 '22 at 19:19

2 Answers2

0

I think what you have looks fairly clean, but for an alternative, you could add format-able strings together and format them in a separate step if you'd like, really this comes down to a matter of opinion:

class User:
    def __init__(self, first_name, last_name, gender, location):
        self.first_name = first_name
        self.last_name = last_name
        self.gender = gender
        self.location = location
        
    def greet_user(self):
        output = ("Hello there {}, you come from the "
                  "{} family. You currently reside in "
                  "{}. Oh, I forgot to mention that you're "
                  "a {}. Have a nice day!")
        output = output.format(self.first_name, self.last_name,
                               self.location, self.gender)
        print(output)
first_name = 'Bob'
last_name = 'Joe'
gender = 'Robot'
location = 'Jupiter'
x = User(first_name, last_name, gender, location)
x.greet_user()

# Output:

Hello there Bob, you come from the Joe family. You currently reside in Jupiter. Oh, I forgot to mention that you're a Robot. Have a nice day!
BeRT2me
  • 12,699
  • 2
  • 13
  • 31
  • Since Python 3.6, shouldn't people be using f-strings for efficient memory use and performance? Adding strings together with '+' or '\n' seems to create more work for the CPU and more operator+= calls. – justdan23 May 05 '23 at 19:56
  • @justdan23 The `+` weren't technically necessary, so I've removed them. As for an efficiency argument... this is python, rarely does anyone do something with python where the minuscule difference in performance will matter to their application. I think the change to the title that was just made will clear up most of the confusion... even if it is a bit verbose :) – BeRT2me May 06 '23 at 20:31
0

It depends on what "clean" code means.

If you are seeking to follow "best practices" as being "clean", then it depends on whether you are dealing with substituting variables provided by user input or not in your formatting.

If user input, then I would use string templates with the ".substitute()" method to prevent code injection attacks.

from string import Template
name = 'Elizabeth'
t = Template('Hey $name!')
t.substitute(name=name)
# 'Hey Elizabeth!'

If not user input, then I would use f-strings if using Python 3.6 or later.

multi = f"""It was the best of times.
It was the worst of times."""

# It was the best of times.
#   It was the worst of times.
print(multi)

As for breaking up strings into different f-strings, I would lean toward one f-string so the compiler or runtime does not need to merge them together first.

In other words, find the "sweet spot" between "pretty" and "efficient" to meet your needs.

Consider the next person who has to take over your code and whether they would appreciate the "pretty" over "efficient" and whether the comments in code explain why so people don't remove the way you implemented it if it makes it more "efficient".

Check out this writeup too which I felt was well written to explain more: https://realpython.com/python-string-formatting/#3-string-interpolation-f-strings-python-36

justdan23
  • 560
  • 7
  • 9
  • It's not clear from OPs post, but they *don't* want line breaks between the lines, they're just looking for a simple way to write a single line across multiple lines of code. – BeRT2me May 06 '23 at 20:10
  • Also, the security issues of using `.format` only really apply when the user has access to modifying the format string itself... which is not the case here. – BeRT2me May 06 '23 at 20:28
  • @BeRT2me You can use f with three quotes at the start and three quotes at the end (like shown in an example above). Although there are line breaks, they are not physical line breaks to the string. If you want physical line breaks, add '\n' characters in the string. – justdan23 Jul 12 '23 at 16:43
  • That's 1000% not true. Simply entering `multi` into a python console clearly outputs `'It was the best of times.\nIt was the worst of times.'` .... it includes the physical line break because you're using triple quotes... Literally just test your own code... – BeRT2me Jul 12 '23 at 20:54