結論:生のプレフィックス指定子の使用をスキップできるように、Python の組み込みのエスケープ シーケンス処理をオーバーライドまたは無効にすることはできません。これを理解するために、Pythonの内部を掘り下げました。したがって、何らかのフレームワークの一部として複雑な文字列 (正規表現など) で動作するオブジェクトを設計しようとする場合は、オブジェクトの文字列引数に接頭辞を含める__init__()
必要があることを docstring で指定してください。r
元の質問:ユーザーが入力した文字列について何も「変更」しないように Python に強制するのは少し難しいと思います。これには、正規表現やエスケープされた 16 進シーケンスが含まれている可能性があります。生の文字列(およびそのデコード対応)のさまざまな組み合わせをすでに試しました.encode('string-escape')
が、正しいアプローチが見つかりません。
ドキュメンテーション IPv6 アドレス のエスケープされた 16 進表現が与えられた場合2001:0db8:85a3:0000:0000:8a2e:0370:7334
、 を使用して.encode()
、この小さなスクリプト ( と呼ばれますx.py
):
#!/usr/bin/env python
class foo(object):
__slots__ = ("_bar",)
def __init__(self, input):
if input is not None:
self._bar = input.encode('string-escape')
else:
self._bar = "qux?"
def _get_bar(self): return self._bar
bar = property(_get_bar)
#
x = foo("\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34")
print x.bar
実行すると、次の出力が生成されます。
$ ./x.py
\x01\r\xb8\x85\xa3\x00\x00\x00\x00\x8a.\x03ps4
\x20
が ASCII スペース文字に変換されていることに注意してください。これは、Python がエスケープされた 16 進シーケンスを処理し、それらを印刷可能な ASCII 値に変換するため、基本的に正しいです。
foo()
次のように、イニシャライザが生の文字列として処理された場合 (および.encode()
呼び出しが削除された場合)、これを解決できます。
x = foo(r"\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34")
ただし、私の最終目標は、使用できる一種のフレームワークを作成することであり、これらの種類の「実装の詳細」をエンドユーザーから隠したいと考えています。上記の IPv6 アドレスをエスケープされた 16 進形式 (生の指定子なし)で呼び出し、すぐにそれを出力した場合、生の指定子を知らずに、または使用せずに入力したものを正確foo()
に返す必要があります。したがって、それを可能にするために必要な処理を に実行させる方法を見つける必要があります。foo
__init__()
編集:この SO questionごとに、常にある種のエスケープシーケンス処理を実行するという点で、Python の欠陥のようです。一時的であっても、エスケープ シーケンス処理を完全にオフにする機能はないようです。最悪。サブクラス化を研究して、Python が文字列で処理したエスケープ シーケンスをインテリジェントに判断し、それらを元の形式に変換するstr
ようなものを作成する必要があると思います。rawstr
これじゃ面白くない…
Edit2:以下のサンプル正規表現を考えると、別の例:
"^.{0}\xcb\x00\x71[\x00-\xff]"
これを var に割り当てるか、生の指定子を使用せず\x71
に関数に渡すと、 は文字に変換されq
ます。.encode('string-escape')
またはを追加しても.replace('\\', '\\\\')
、エスケープ シーケンスは処理されます。したがって、次の出力が得られます。
"^.{0}\xcb\x00q[\x00-\xff]"
生の指定子を使用せずに、どうすればこれを停止できますか? エスケープシーケンス処理を「オフ」にするか、「元に戻す」ための方法はありq
ます\x71
か? エスケープ シーケンスの処理が行われる前に、文字列を処理してバックスラッシュをエスケープする方法はありますか?