文字列

Python 3 の文字列 (str) はユニコードになっていて、バイト列 (bytes) と明確に区別されています。 (開発がキャンセルされましたが、 php 6 でも Unicode 対応予定でした)

リテラル

Python での文字列リテラルは、クォートと prefix で構成されています。 まずはクォートと prefix にどんなパターンがあるのかを列挙していきます。

  • クォート

    • シングルクォート 'foo'
    • ダブルクォート "foo"
    • 3重シングルクォート '''foo'''
    • 3重ダブルクォート """foo"""
  • prefix

    • Unicode prefix u"ほげ"
    • Byte prefix b"foo"
    • raw prefix r"foo\bar"
    • byte + raw br"homu\homu"

クォートと prefix は任意の組み合わせが可能です。

Byte prefix をつけた場合はバイト列になります。

Unicode prefix は Python 3.3 で追加された構文で、 prefix なしの場合と変わりません。 ただし、 Python 2 では unicode prefix がないとバイト文字列 (Python 2 ではバイト列も 文字列だった) になるので、 Python 2 と 3 両方をサポートするために使われることが あります。

raw prefix はほとんどのエスケープが効かなくなり、正規表現を書きやすくなります。

php のダブルクォート文字列は Python でどう書くの?

php のダブルクォート文字列は、 Python の普通の(prefixの無い1重の)シングル クォートやダブルクォートに似ていますが、変数展開ができません。 その代わりに、 php の sprintf に似た format メソッドを使います。

<?php

$hoge = "xxx";
$homu = "yyy";

$s = "foo $bar baz{$homu}foo"; // "foo xxx bazyyyfoo"
hoge = 'xxx'
homu = 'yyy'
s = "foo {0} baz{1}foo".format(hoge, homu)         # 引数の順番でフォーマット
s = "foo {xx} baz{yy}foo".format(xx=hoge, yy=homu) # 引数の名前でフォーマット
s = "foo {hoge} baz{homu}foo".format(**vars())     # 変数名をそのまま引数の名前に

Python では、シングルクォートとダブルクォートにほとんど差はありません。唯一の差は、 シングルクォート内ではダブルクォートをエスケープ無しで使え('foo"bar')、 ダブルクォート内ではシングルクォートをエスケープ無しで使える("foo'bar") ことです。

php のシングルクォート文字列は Python でどう書くの?

php のシングルクォート文字列は、シングルクォートをエスケープする \\' 以外のエスケープが効かなくなります。正規表現を書くときなんかに便利ですね。

これは Python では r の prefix を使います。

<?php
$s = '\d{3}-\d{4}';
s = r"\d{3}-\d{4}"

php のヒアドキュメントは Python でどう書くの?

php のヒアドキュメントは複数行の文字列を手軽に書けます。これは、 Python では 3重クォートで書きます。

<?php

$s = <<EOF
あいうえお
かきくけこ
EOF
s = """\
あいうえお
かきくけこ
"""

最初の一行でエスケープしているのは、文字列の先頭に改行が入るのを防ぐためです。 ダブルクォートだけでなく、シングルクォートを3重にすることもできます。

エンコードとデコード

文字列をエンコードするとバイト列に、バイト列をデコードすると文字列になります。

>>> s = 'foo'
>>> s.encode()
b'foo'
>>> s.encode().decode()
'foo'

エンコードするときに使われる文字コードはデフォルトで UTF-8 ですが、 別の文字コードを指定することもできます。

>>> s = 'foo'
>>> s.encode('cp932')
b'foo'

文字列連結

php の . 演算子の代わりに、 Python は + 演算子を使います。

<?php
$foo = "foo";
$bar = "bar";
$foobar = $foo . $bar;
foo = "foo"
bar = "bar"
foobar = foo + bar

ただし、注意しないといけない点として、 Python の + は数値など文字列以外の オブジェクトを自動に文字列化してくれません。その場合は str 関数を使うか、 format メソッドを使って下さい。

<?php
$foo = 23;
$bar = 42;
$foobar = $foo . ':' . $bar;
foo = 23
bar = 42
foobar = str(foo) + ':' + str(bar)
foobar = '{0}:{1}'.format(foo, bar)

文字列検索

ある文字列 a が、部分文字列 b を含んでいるかどうかをテストする場合、 php だと

<?php
if (strpos(a, b) !== false) # b が a に含まれる
if (strpos(a, b) === 0)     # b が a の先頭から始まる部分文字列

のように書きますが、 Python だと

if b in a:                  # 部分文字列として含む
if a.startswith(b):         # 先頭に部分文字列として含む

の様に、読みやすく書くことができます。本当に何文字目に出現するかを調べたい場合は、 文字列の find メソッドか index メソッドを使います。2つのメソッドの違いは、 部分文字列が出現しなかった場合の動作で、 find は -1 を返し、 index は例外を 発生させます。

>>> s = "foobar"
>>> s.index("ob")
2
>>> s.index("bo")
Traceback (most recent call last):
  File "<ipython-input-6-10ac0078e622>", line 1, in <module>
    s.index("bo")
ValueError: substring not found
>>> s.find("bo")
-1

スライス

文字列 s に対して s[3] とすると3文字目の文字を得ることができます。 この添字は s[i:j]s[i:j:k] の形で書くこともできます。 i は開始位置、 j は終了位置、 k はステップ数です。

>>> s = "abcdefghijklmn"
>>> s[3]
'd'
>>> s[:3]
'abc'
>>> s[3:]
'defghijklmn'
>>> s[::-1]
'nmlkjihgfedcba'
>>> s[::2]
'acegikm'

php の文字列処理関数を Python に置き換える

sprintf

Python には組み込みの文字列フォーマット方法が2種類あります。 1つは、上で php のダブルクォート内の変数展開を置き換える方法として紹介した format メソッドです。もうひとつがC言語の sprintf スタイルの方法です。 format メソッドの方が新しくて高機能ですが、 sprintf スタイルの方法も今のところ 廃止される予定はありません。

Python で sprintf スタイルの書式化をするには、次のように書きます.

>>> "%s %s %s" % ('foo', 0, None)
'foo 0 None'

書式指定文字列に %s を利用することで、文字列以外のオブジェクトも文字列化してフォーマットできます。 %s の代わりに %d%f などの書式指定文字を利用することで、数値の書式をより詳細に 指定できます。その場合、与えるデータが数値型でないとエラーになることに注意してください。

>>> "%03d %.4f" % (10, 0.111111)
'010 0.1111'
>>> "%03d %.4f" % ('10', '0.1')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: %d format: a number is required, not str

ここまでの例で、文字列、 % の次に書いていた (10, 0.111111) の部分は tuple といって、後で説明します。 tuple の代わりに dict を使うことで、データの表示位置を順序ではなく名前で指定できます。 dict についても、後で説明します。

>>> "%(foo)s %(bar)s %(foo)s" % {'bar': 5, 'foo': 0}
'0 5 0'

書式指定についての詳細は、 文字列フォーマット操作 を参照してください。 を参照してください。 format メソッドについては 文字列の書式化 を参照してください。

explode

文字列を区切り文字で分割するには、文字列の split メソッドを利用します。

>>> "foo,bar,baz".split(',')
['foo', 'bar', 'baz']
>>> "foo==bar==baz".split('==')
['foo', 'bar', 'baz']
>>> "".split(',')
['']
>>> "foo bar  baz ".split(' ')
['foo', 'bar', '', 'baz', '']

このメソッドで指定できる区切り文字は正規表現ではなくただの文字列なのですが、 特殊なケースとして、引数を省略すると “1つ以上の空白文字” を区切り文字として認識し、 前後の空白文字も無視する便利関数になります。

>>> "foo   bar \t baz   ".split()
['foo', 'bar', 'baz']

implode

逆に文字列を連結するには、文字列の join メソッドを利用します。

>>> ','.join(['foo', 'bar', 'baz'])
'foo,bar,baz'
>>> ''.join(['foo', 'bar', 'baz'])
'foobarbaz'

注意点として、 join メソッドは文字列以外のデータが来るとエラーになります。 文字列以外のデータを文字列として連結したい場合は、 str 関数などを使って 文字列に変換する必要があります。

>>> ''.join([1,2,3])   # 数値を連結仕様とするとエラー
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: sequence item 0: expected string, int found
>>> str(1)             # str で文字列に変換できる
'1'
>>> list(map(str, [1,2,3]))  # map を使ってリストの要素を一括変換できる
['1', '2', '3']
>>> ''.join(map(str, [1,2,3]))  # map と str とjoin を組み合わせる
'123'

bin2hex, hex2bin

<?php
$hex = bin2hex('foobar');
$foo = hex2bin($hex);

文字列は Unicode なので、一旦バイト列に変換してから HEX に変換します。

>>> s = 'foobar'
>>> import binascii
>>> binascii.b2a_hex(s.encode())
b'666f6f626172'

chr

php と同じです。

<?php
$s = chr(70);
s = chr(70)

nl2br

replace メソッドを使います。

>>> "foo\nbar".replace('\n', '<br>')
'foo<br>bar'

trim, ltrim, rtrim

strip, lstrip, rstrip というメソッドがあります。

>>> s = "  foo "
>>> s.strip()
'foo'
>>> s.lstrip()
'foo '
>>> s.rstrip()
'  foo'

デフォルトでは空白文字を取り除きますが、取り除く文字を引数で指定できます。

strrev

スライスを使います。

>>> "foo"[::-1]
'oof'