web-dev-qa-db-ja.com

pythonでの複数行文字列のフォーマット

まず、次のような目的の出力を取得できるようにしています。

*********************************************************************
                                 hello
********************************************************************* 

これを達成するために、複数行の文字列を持つ変数への望ましい出力を割り当て、formatで同じものを出力しました。

$ cat varibale.py 
decorator = """ **********************************************************************
                               {}
            ********************************************************************** """
print(decorator.format("hello"))

出力:

**********************************************************************
                               hello
            **********************************************************************

上記のアプローチの問題は出力の3行目の余分なスペースであり、これは奇妙に見えます。

これは次の方法で実現できます

$ cat varibale.py 
decorator = """ **********************************************************************
                             {}
********************************************************************* 
"""
print(decorator.format("hello"))

出力:

 **********************************************************************
                             hello
********************************************************************* 

しかし、この方法ではインデントに従っていないため、私のコードは見栄えがよくありません。

望ましい出力を実現するための正しい方法を提案してください。

9
Here_2_learn

複数行のリテラル文字列を美しく見せるための1つの方法は、次のようにバックスラッシュを使用して改行をエスケープすることです。

_s = '''\
*********************************************************************
                                 hello
*********************************************************************
'''
print(s)
_

出力

_*********************************************************************
                                 hello
*********************************************************************
_

ただし、PEP-008はそのようなバックスラッシュの使用を推奨していません。壊れやすいです。バックスラッシュと改行の間にスペースがある場合、改行はエスケープされず、バックスラッシュが印刷されます。

より用途の広いアプローチは、テキストを中央揃えするために必要なパディングの量を計算し、ネストされた書式指定子を介してそれを適用する関数を使用することです。例えば:

_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))
_

出力

_*********************************************************************
                                hello
*********************************************************************
****************
  Hello, world
****************
_

使い方

そのフォーマット文字列は少し密集しているので、説明しようと思います。 ;)このトピックの詳細については、ドキュメントの Format String Syntax を参照してください。以下の説明は、それらのドキュメントを借用し、言い換えたものです。

_'{0}\n{1:>{2}}\n{0}'.format(stars, s, pad)
_

フォーマット文字列の_{}_で囲まれたものは、「置換フィールド」と呼ばれます。置換フィールドの最初の項目は、オプションのフィールド名です。これにより、_.format_のどの引数がこの置換フィールドに対応するかを識別できます。フィールド名にはいくつかのバリエーションがあります。このフォーマット文字列は数値名を使用するため、_.format_ argsを位置で識別します。つまり、0はstarsに対応し、1はsに対応し、2はpadに対応します。

フィールド名が指定されていない場合、0、1、2、...などの数字が自動的に入力されます(Python 2.6を使用している場合を除き、フィールド名は必須です)。ほとんどの場合に役立つため、ほとんどのフォーマット文字列はフィールド名を使用する必要はありません。

フィールド名の後に、値がどのように提示されるかを説明する「フォーマット指定子」または「フォーマット指定」を与えることができます。コロン_:_は、フィールド名とフォーマット仕様を区切ります。フォーマット仕様を指定しない場合は、デフォルトの仕様が得られ、ほとんどの場合それで十分です。しかし、ここではもう少し制御したいので、フォーマット仕様を指定する必要があります。

フォーム仕様では、_>_記号により、フィールドが使用可能なスペース内で右揃えになります。位置合わせ記号の後に、フィールドの最小幅を指定する数値を指定できます。フィールドは必要に応じて自動的に大きくなります。

たとえば、'{0:>6}'.format('test')は、引数0( 'test')を少なくとも6文字幅で右揃えのスペースに配置することを示しています。その結果、文字列_' test'_になります。

ただし、形式仕様には実際にまったく新しい置換フィールドを含めることができます。これにより、フィールド幅を制御する変数を提供できます。したがって、私のフォーマット文字列_{1:>{2}}_では、ここにarg 1(s)を配置し、arg 2(pad)で指定された幅のフィールドに右揃えします。置換フィールドのネストは1レベルしか許可されていませんが、実際にはより深いネストが必要な状況を考えるのは困難です。

したがって、すべてをまとめると、_'{0}\n{1:>{2}}\n{0}'_は、_.format_に、デフォルトのフォーマット仕様を使用してarg 0(stars)で始まり、改行が続き、その後にarg 1( s)幅padのフィールドに右揃えし、その後に別の改行が続き、最後に再び引数0(stars)が続きます。

それで十分だと思います。 :)


Python 3.6+では、f-stringを使用できます:

_def banner(s, width=69):
    stars = '*' * width
    pad = (width + len(s)) // 2
    return f'{stars}\n{s:>{pad}}\n{stars}'
_
7
PM 2Ring

あなたは例えば次のように進めることができます:

print('*'*80)
print('{msg:^80s}'.format(msg = 'HELLO')) #^ centers the message
print('*'*80)

または、テキスト幅を動的にしたい場合:

def fn(msg, w = 80):
    delim = '*'*w
    fmt = '{msg:^%ds}'%w

    print(delim)
    print(fmt.format(msg=msg))
    print(delim)

fn('hello')

またはファイルに書き込む必要がある場合は、少し一般化されたバージョン:

import sys

def fn(msg, w = 80, F = sys.stdout):
    delim = '*'*w
    fmt = '{delim:s}\n{msg:^%ds}\n{delim:s}\n'%w
    F.write(fmt.format(delim = delim, msg = msg))

fn('hello')
6
ewcz

多分 :

print '*' * 80 + '\n' + ' ' * 38 + 'hello' + '\n' + '*' *80

またはpython3の場合

a = lambda x,c,mess: print(c*x + ('\n' if not mess else mess))
a(80, '*', None)
a(38, ' ', 'Hello')
a(80, '*', None)
0
rajkris

別の方法は textwrap モジュールを使用することです

import textwrap

decorator = """\
            ****
            {0}
            ****"""

print(textwrap.dedent(decorator.format("hello")))
0
Ludisposed