5

数式を表す長い文字列 (それぞれ 9000 文字以上) が多数あります。私は元々、Python のシンボリック代数パッケージである sympy を使用して式を生成しました。切り捨てられた例は次のとおりです。

a = 'm[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 + zb[layer]*m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 - zt[layer]*m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[layer])'

文字列内のテキストをコピーしてから is as code を使用します (つまり、' と ' の間のテキストをコピーしてから、コードとして関数に貼り付けます):

def foo(args):
    return m[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 + zb[layer]*m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 - zt[layer]*m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[layer])

長いコード行は扱いにくくなり、IDE (Spyder) の速度が低下するため、いくつかの改行を挿入したいと考えています (コードは 1 つの長い行として正常に動作します)。式を括弧で囲み、自分で改行を挿入することで、手動でこれを成功させました (つまり、 PEP8 に従って暗黙的な行の継続を使用します)

def foo(args):
    return (m[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 + 
        zb[layer]*m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 - 
        zt[layer]*m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[layer]))

改行を挿入する関数または機能が欲しいです。モジュールを使用してみましtextwrapたが、行が不適切な場所に分割されます。たとえば、以下のコードでは、最後の行が「レイヤー」の途中で分割され、数式が無効になります。

>>> import textwrap
>>> a = 'm[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 + zb[layer]*m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 - zt[layer]*m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[layer])'
>>> print(textwrap.fill(a,width=70))
m[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 +
zb[layer]*m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 - 
zt[layer]*m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[lay
er])

文字列を手動で分割し、文字列をコードとして貼り付けたときに有効な式を保持するための私の経験則は次のとおりです。

  1. 式全体を で囲み()ます。
  2. 空白または , , , の後に約 70 文字幅で+分割-します。*])
4

1 に答える 1

8

まず、通すだけで途中でbreak_long_words=False割れにくくなります。label

しかし、それだけでは問題を解決するには不十分です。出力は有効ですが、70 列を超える場合があります。あなたの例では、次のようになります。

m[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 +
zb[layer]*m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 -
zt[layer]*m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[layer])

幸いなことtextwrapに、世の中のすべてを実行できるわけではありませんが、優れたサンプル コードも作成されます。そのため、ドキュメントはソースに直接リンクしています。

あなたが望むのは本質的に ですがbreak_on_hyphens、算術演算子も壊れています。したがって、正規表現を で使用するように変更するだけであれば、それで十分(-|\+|\*\*|\*)かもwordsep_reしれません。または、もう少し手間がかかるかもしれませんが、そこから簡単に理解できるはずです。

次に例を示します。

class AlgebraWrapper(textwrap.TextWrapper):
    wordsep_re = re.compile(r'(\s+|(?:-|\+|\*\*|\*|\)|\]))')
w = AlgebraWrapper(break_long_words=False, break_on_hyphens=True)
print w.fill(a)

これにより、次のことが得られます。

m[i]**2*(zb[layer]*m[i]**4 - 2*zb[layer]*m[j]**2*m[i]**2 + zb[layer]*
m[j]**4 - zt[layer]*m[i]**4 + 2*zt[layer]*m[j]**2*m[i]**2 - zt[layer]*
m[j]**4)**(-1)*ab[layer]*sin(m[i]*zb[layer])*sin(m[j]*zb[layer])

しかし、実際には、括弧や括弧で区切る必要がなかったのは幸運でした。なぜなら、私が書いたのと同じくらい簡単なので、括弧の前と括弧の後と同じように簡単に壊れるからです。これは構文的に有効ですが、非常に醜い。演算子についても同じことが言えますが、 a の前でブレークする方が a*よりもはるかに見苦しくありません]。したがって、おそらく実際の演算子だけに分割して、そのままにしておきます。

wordsep_re = re.compile(r'(\s+|(?:-|\+|\*\*|\*))')

それが受け入れられない場合は、実際に必要な正規表現を考え出し、それを の代わりにドロップする必要がありますwordsep_re


別の解決策は、装飾-ラップ-非装飾です。例えば:

b = re.sub(r'(-|\+|\*\*|\*', r'\1 ', a)
c = textwrap.fill(b)
d = re.sub(r'(-|\+|\*\*|\*) ', r'\1', c)

もちろん、これは完璧ではありません。追加されたスペースよりも既存のスペースを優先するわけではなく、70 列未満でいっぱいになります (追加されたスペースを制限に向かってカウントするため)。しかし、何か手っ取り早くて汚いものを探しているだけなら、役立つかもしれません。


いずれにせよ、全体を括弧で囲む最も簡単な方法は、前もってそれを行うことです。

if len(a) >= 70:
    a = '({})'.format(a)
于 2013-10-22T00:13:39.433 に答える