To begin with, I am working to a get a desired output like this:
*********************************************************************
hello
*********************************************************************
To achieve this I have assigned the desired output to a variable with multiline string and printing the same with format.
$ cat varibale.py
decorator = """ **********************************************************************
{}
********************************************************************** """
print(decorator.format("hello"))
Output:
**********************************************************************
hello
**********************************************************************
The issue with above approach is the extra spaces in the third line of output which is looking odd.
I am able to achieve this in the following way:
$ cat varibale.py
decorator = """ **********************************************************************
{}
*********************************************************************
"""
print(decorator.format("hello"))
Output:
**********************************************************************
hello
*********************************************************************
But this way my code doesn't look good, as it is not following the indentation.
Please suggest the right way to achieve the desired output.
As expected, the floating point number (1.9876) was rounded up to two decimal places – 1.99. So %. 2f means to round up to two decimal places. You can play around with the code to see what happens as you change the number in the formatter.
%s is used as a placeholder for string values you want to inject into a formatted string. %d is used as a placeholder for numeric or decimal values.
One way to make multi-line literal strings look good is to use a backslash to escape the newline, like this:
s = '''\
*********************************************************************
hello
*********************************************************************
'''
print(s)
output
*********************************************************************
hello
*********************************************************************
However, PEP-008 discourages backslash usage like that. It's too fragile: if there's a space between the backslash and the newline then the newline won't get escaped, and the backslash will get printed.
A more versatile approach is to use a function which calculates the amount of padding required to centre the text, and applies it via a nested formatting specifier. For example:
def banner(s, width=69):
stars = '*' * width
pad = (width + len(s)) // 2
return '{0}\n{1:>{2}}\n{0}'.format(stars, s, pad)
print(banner('hello'))
print(banner('Hello, world', width=16))
output
*********************************************************************
hello
*********************************************************************
****************
Hello, world
****************
That format string is a little dense, so I guess I should try to explain it. ;) For full information on this topic please see Format String Syntax in the docs. The explanation below borrows from & paraphrases those docs.
'{0}\n{1:>{2}}\n{0}'.format(stars, s, pad)
The stuff enclosed in {}
in a format string is called a "replacement field". The first item in a replacement field is the optional field name. This lets us identify which arg of .format
goes with this replacement field. There are a couple of possible variations for field names, this format string uses numeric names, so it identifies the .format
args by their position. That is, 0 corresponds to stars
, 1 corresponds to s
and 2 corresponds to pad
.
If no field names are given they get automatically filled by the numbers 0, 1, 2, ... etc (unless you're using Python 2.6, where field names are mandatory). That's quite useful most of the time, so most format strings don't bother using field names.
After the field name we can give a "format specifier" or "format spec" which describes how the value is to be presented. A colon :
separates the field name from the format spec. If you don't supply a format spec then you get a default one, and most of the time that's adequate. But here we do want a little more control, so we need to supply a format spec.
In a form spec the >
sign forces the field to be right-aligned within the available space. After the alignment sign we can provide a number to specify the minimum field width; the field will automatically be made larger if necessary.
For example, '{0:>6}'.format('test')
says to put argument 0 ('test') in a space that's at least 6 chars wide, aligned to the right. Which results in the string ' test'
.
But a format spec can actually contain a whole new replacement field! This allows us to supply a variable to control the field width. So in my format string {1:>{2}}
says to put arg 1 here (s
), right aligned in a field with a width given by arg 2 (pad
). Only one level of replacement field nesting is permitted, but it's hard to think of a situation where you'd actually want deeper nesting.
So putting it all together: '{0}\n{1:>{2}}\n{0}'
tells .format
to build a string that starts with arg 0 (stars
) using the default format spec, followed by a newline, followed by arg 1 (s
) right aligned in a field of width pad
, followed by another newline, finally followed by arg 0 (stars
) again.
I hope that made enough sense. :)
In Python 3.6+, we could use an f-string:
def banner(s, width=69):
stars = '*' * width
pad = (width + len(s)) // 2
return f'{stars}\n{s:>{pad}}\n{stars}'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With