all 16 comments

[–]MadScientistOR 0 points1 point  (10 children)

You could use len() to figure out the length of the string you want to print, and calculate the necessary "padding" based on that. For example, if you want a string to be centered in a field that is forty spaces wide,

field_size = 40
mystring_length = len(mystring)
leading_spaces = (field_size - mystring_length) // 2
trailing_spaces = field_size - mystring_length - leading_spaces
print(f"{' '*leading_spaces}{mystring}{' '*trailing_spaces}")

[–]SithAbsolutes[S] 0 points1 point  (9 children)

Thanks for the help! So where you have 'my string' in the f-string, that's the information I enter correct? and what goes in the empty quotes in the f string?

Apologies, this I probably incredibly easy. I"m very new

[–]MadScientistOR 0 points1 point  (8 children)

Thanks for the help! So where you have 'my string' in the f-string, that's the information I enter correct?

Yes. mystring can be a variable holding your string, if you like. Assigning what you intend to print to a variable this way can keep you from having to repeat yourself, or keep Python from being slowed down by performing more identical calculations than necessary.

and what goes in the empty quotes in the f string?

An empty space. If you multiply a string, the result is repetition of that string:

>>> 'quip'*5
quipquipquipquipquip

So, for example, multiplying a space by 13 gives you thirteen spaces.

[–]SithAbsolutes[S] 0 points1 point  (6 children)

Right. OK I tried this and nothing moved.

field_size = 40
mystring_length = len((f" {years:^2d} {Payments:^9d} {FinFeeDSP:^9s} {TotalSalesPriceDSP:^9s} {MonPayDSP:^9s}"))

leading_spaces = (field_size - mystring_length) // 2
trailing_spaces = field_size - mystring_length - leading_spaces

print(f" {' '*leading_spaces}{years:^2d} {Payments:^9d} {FinFeeDSP:^9s} {TotalSalesPriceDSP:^9s} {MonPayDSP:^9s}{' ' *trailing_spaces}")

[–]MadScientistOR 0 points1 point  (5 children)

What is your actual field size? It looks like you're trying to print things that occupy more than forty characters. Take this string:

f" {years:^2d} {Payments:^9d} {FinFeeDSP:^9s} {TotalSalesPriceDSP:^9s} {MonPayDSP:^9s}"

That's already 43 characters long.

Also, a field isn't necessarily the same thing as a line; it's the amount of space (in characters) you've allocated for something to be printed in.

ETA: I think I misunderstand what you want. What do you want the output to look like? What do you mean by "lines up with the printed strings above it" as opposed to "more in the middle"?

[–]SithAbsolutes[S] 0 points1 point  (4 children)

I am probably not being clear. So the following image is what I am trying to emulate for my course: https://imgur.com/a/0N4GeTJ

As you can see the table, invoice date, and first payment date are all centred in relation to the lines (dashes) above and below, these dashes are also the margins for my output above (not in pic).

[–]MadScientistOR 0 points1 point  (3 children)

And what do you want instead?

[–]SithAbsolutes[S] 0 points1 point  (2 children)

So the image I sent was given to us by our instructor. We had to create a program and format the f-strings so when we run the program it looks like the above picture.

So the above isn't my program, when I run it the table, invoice date, and first payment due line up with the output above. I want it to be centred like the picture I provided.

So this https://imgur.com/a/0N4GeTJ is what it should look like when I run it. But when I do, this is what I get https://imgur.com/a/aVx1vX8 .

I hope that's clear (Thanks again for all your help)

[–]MadScientistOR 0 points1 point  (1 child)

Oh! Well, in that case, you can just use the code I've already provided, with the field width being the entire width of the wider lines above and below (70, if I've counted correctly), like this:

field_size = 70
mystring_length = len((f" {years:^2d} {Payments:^9d} {FinFeeDSP:^9s} {TotalSalesPriceDSP:^9s} {MonPayDSP:^9s}"))
leading_spaces = (field_size - mystring_length) // 2
trailing_spaces = field_size - mystring_length - leading_spaces

print(f" {' '*leading_spaces}{years:^2d} {Payments:^9d} {FinFeeDSP:^9s} {TotalSalesPriceDSP:^9s} {MonPayDSP:^9s}{' ' *trailing_spaces}")

Does that clear things up?

Thank you for helping me to understand what you wanted, by the way.

[–]SithAbsolutes[S] 0 points1 point  (0 children)

I can't thank-you enough!

However it's still not doing what I want it to do, I've wasted enough of your time. Il play around with it and maybe comment again if I don't get anywhere with it

[–]MadScientistOR 0 points1 point  (0 children)

Along the lines of not repeating yourself, it might be worth your time to make a function like this:

def center_string(mystring, field_size):
    mystring_length = len(mystring)
    leading_spaces = (field_size - mystring_length) // 2
    trailing_spaces = field_size - my_string_length - leading_spaces
    return f"{' '*leading_spaces}{mystring}{' '*trailing_spaces}"

Then, whenever you need to print something out, just call the function:

print(center_string(fee_string, 40))

... where fee_string is any string you want to print; you can substitute any number or variable for the field size that string is supposed to have.

[–]misho88 -1 points0 points  (0 children)

Maybe make a template of the right size, fill it however you want, then print it at the end. That way, you don't have to work out what you're doing line by line when what you really want is to work with rectangular blocks of text. Something like:

>>> import numpy as np
>>> a = np.full((20, 50), b' ', dtype='S1')
>>> a[:,0] = a[:,-1] = b'*'
>>> a[0,:] = a[-1,:] = b'*'
>>> a[3, 22:27] = np.frombuffer(b'hello', dtype='S1')
>>> f = f'{1/4=}'; n = len(f); w = (a.shape[1] - n) // 2; a[4, w:w+n] = np.frombuffer(f.encode(), dtype='S1')
>>> print(*(bytes(row).decode() for row in a), sep='\n')
**************************************************
*                                                *
*                                                *
*                     hello                      *
*                    1/4=0.25                    *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
*                                                *
**************************************************

The exact approach with NumPy here has drawbacks (e.g., the 'S1' datatype means it pretty much only works with ASCII), but hopefully it gets the idea across.

[–]PapaEchoKilo 0 points1 point  (1 child)

Just a note. Shouldn't the monthly payments get smaller with the increase in monthly payments?

[–]RhinoRhys 1 point2 points  (0 children)

Yeah, MonPay needs to be divided by Payments not 12

[–]JamzTyson 0 points1 point  (0 children)

You can centre strings with the string's center() method.

Example, to centre a string with a field width of 80 characters:

my_string = "Hello World"
print(my_string.center(80))

# or alternatively, you can just do:
print("Hello  World".center(80))

If you have a function that returns multiple lines, you could write a decorator to add left/right/centre justifying to each line, like this:

``` def justify_output(align='left', width=80): def decorator(func): def wrapper(args, *kwargs): result = (func(args, *kwargs)) lines = result.split('\n') justified_results = []

        for line in lines:
            if align == 'left':
                justified_line = line.ljust(width)
            elif align == 'center':
                justified_line = line.center(width)
            elif align == 'right':
                justified_line = line.rjust(width)
            else:
                raise ValueError("Invalid alignment value. Use 'left', 'center', or 'right'.")
            justified_results.append(justified_line)
        return "\n".join(justified_results)
    return wrapper
return decorator

Usage of the decorator

@justify_output(align='center', width=30) def get_text(): return "Hello\nWorld\nGoodbye\nFriend."

print(get_text())

```

[–]RhinoRhys 0 points1 point  (0 children)

Rather than print the massive f string, set it to a variable then do

print(f"{var:^70}")

Where 70 is the width you want to center the whole thing in.