削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
タグ: 2017年版ソースエディター
全て作業中に移動
35 行
== 整理作業中 ==
* [[Python/整理中]] (複素数、正規表現、HTTPクライアント、JSON、pass)
 
=== 内包表記とジェネレータ式 ===
Pythonには、シーケンスの内包表記とジェネレータ式があります。
;[https://paiza.io/projects/zcGKAf9f-uN9V7KQrpv4SQ?language=python3 内包表記とジェネレータ式]:<syntaxhighlight lang="python">
for label, expr in {"加算":"1 + 1",
"リスト内包表記":"[2 ** x for x in range(5)]",
"集合内包表記":"{2 ** x for x in range(5)}",
"辞書内包表記":"{x: 2 ** x for x in range(5)}",
"ジェネレータ式":"(2 ** x for x in range(5))",
"タプルコンストラクターにジェネレータ式を適用":"tuple(2 ** x for x in range(5))",
}.items() :
print(f'''{label}:
{expr}
⇒ {eval(expr)} : {type(eval(expr))}''')
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
加算:
1 + 1
⇒ 2 : <class 'int'>
リスト内包表記:
[2 ** x for x in range(5)]
⇒ [1, 2, 4, 8, 16] : <class 'list'>
集合内包表記:
{2 ** x for x in range(5)}
⇒ {1, 2, 4, 8, 16} : <class 'set'>
辞書内包表記:
{x: 2 ** x for x in range(5)}
⇒ {0: 1, 1: 2, 2: 4, 3: 8, 4: 16} : <class 'dict'>
ジェネレータ式:
(2 ** x for x in range(5))
⇒ <generator object <genexpr> at 0x14ac1a9e56d0> : <class 'generator'>
タプルコンストラクターにジェネレータ式を適用:
tuple(2 ** x for x in range(5))
⇒ (1, 2, 4, 8, 16) : <class 'tuple'>
</syntaxhighlight>
: Pythonの式を表す文字列(Ex. "1 + 1")を要素としたタプルをループ変数exprで回しています。
: <code> print(f'{label}:\n {expr}\n ⇒ {eval(expr)} : {type(eval(expr))}')</code>は、
::<syntaxhighlight lang=text>
ラベル:
⇒ 式の評価結果 : 式の評価結果の型
</syntaxhighlight>を表示します。
: <code>(2 ** x for x in range(5))</code>は、タプル内包表記…ではなく、'''ジェネレータ式'''で未評価のシーケンス(generator)を返します(組込み関数のrange同様、この時点ではメモリーオブジェクトではありません)。
: タプルのコンストラクターにジェネレータ式を渡すと、タプルが返ります(タプルはイミュータブルですがメモリーオブジェクトです)。
 
=== 代入演算子 ===
if文やwhile文の条件には式が要求されるので代入文 <code>=</code> は使えませんでした。
しかし、条件式の中で代入を行うのがふさわしいケースもあります。
このため Python 3.8で、条件式中でもつかえる代入演算子(''Assignment Expressions'') <code>:=</code> (俗称:セイウチ演算子;''Walrus operator'')が導入されました<ref>{{Cite web
|title=PEP 572 -- Assignment Expressions
|url=https://www.python.org/dev/peps/pep-0572/
|date=2018/02/28
|accessdate=2021/11/12
}}</ref>。
 
;[https://paiza.io/projects/WZAGYZS0LP5H1o3XpD4vnw?language=python3 代入演算子の使用例]:<syntaxhighlight lang="python">
a = "1234567" # 7文字
if (n := len(a)) > 5:
print("文字が5文字より多いです" , n - 5, "文字オーバー")
print(f"あなたは{n} 文字を入力しました")
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
文字が5文字より多いです 2 文字オーバー
あなたは7 文字を入力しました
</syntaxhighlight>
 
代入演算子を使った条件式を含む文のブロックの外に出ても、そのまま代入した効果は残ります。
 
なお、<code>f"あなたは{n} 文字を入力しました"</code>はテンプレート・リテラルです。
{{See|[[/数値入力と文字入力と出力表示#テンプレート・リテラル]]}}
 
=== エスケープシーケンス ===
たとえばprint()関数で、「こんにちは」と表示させたい場合なら
:<syntaxhighlight lang=pythin3>
print("こんにちは")
</syntaxhighlight>
と書きました。
では、'''"''' を含んだ文字列を表示するにはどうしたら良いでしょう?
やり方は、いくつかあります。
; " を含んだ文字列を表示する方法:<syntaxhighlight lang="python" line>
print('"')
print("\"")
print("\42")
print("\x22")
</syntaxhighlight>
# クオート文字を ' に変えました。素朴ですがパワフルな方法です。
#: しかし、この方法では " と ' は1つの文字列の中で共存できません。
# " の前に \ を前置すると文字列を閉じる " を打消すことができます。
#: \ は、¥(円記号)の半角で表示されるかもしれませんが、文字コードと機能は同じです。
# \ に続けて " の文字コードを8進数で表記します。
#: 10進数ではないので注意してください。
# \ に続けて x それに続けて文字コードを16進数で表記します。
2. から 4. の様に、 \ を前置して文字列中に所望に文字を書く方法を'''エスケープシーケンス'''( ''escape sequence'' )といい、エスケープシーケンスに前置する文字 ' をエスケープ文字( ''escape character'' )といいます。
 
=== エスケープシーケンスの一覧 ===
:{| class="wikitable"
|+ エスケープシーケンスの一覧
! エスケープシーケンス !! 意味
|-
! \<改行>
|バックスラッシュと改行を無視
|-
! \\
|バックスラッシュ自身 (<code>\</code>)
|-
! \'
|シングルクォーテーション (<code>'</code>)
|-
! \"
|ダブルクオーテーション (<code>"</code>)
|-
! \a
|ASCII ベル(アラート) (BEL)
|-
! \b
|ASCII バックスペース (BS)
|-
! \f
|ASCII フォームフィード (FF)
|-
! \n
|ASCII ラインフィード (LF)
|-
! \r
|ASCII キャリッジリターン (CR)
|-
! \t
|ASCII 水平タブ (TAB)
|-
! \v
|ASCII 垂直タブ (VT)
|-
! \ooo
| 8進数キャラクタコードによる文字指定 ''ooo''
|-
! \xhh
| 16進数キャラクタコードによる文字指定 ''hh''
|-
! \uxxxx
| 16ビットの16進数値xxxxを持つUnicode文字
|-
! \Uxxxxxxxx
| 32ビットの16進数値xxxxxxxxを持つUnicode文字
|}
 
=== print関数 ===
<syntaxhighlight lang="python">
# 「ようこそ」 と出力
print("ようこそ")
</syntaxhighlight>
 
<nowiki>#</nowiki>から行末まではコメントです。文字列の出力は<code>print()</code>を使います。Python 2までは<code>print</code>は文でしたが、Python 3では[[Python/組込み関数#print|組込み関数print]]となったため、かっこが必須となります。
 
文字列は<code>" "</code>で囲んでも<code><nowiki>' '</nowiki></code>で囲んでも同じ意味であり、エスケープ文字の取り扱いに違いはありません。
 
=== 備考 ===
* インデントについて
Pythonのブロックはスペース4つのインデントによって表されます(オフサイドルールといいます)。
 
* pythonについて
pythonは、Googleなどの企業のみならず、MITの初年度のプログラミングの授業でも採用されています。英語圏では[[Ruby]]や[[Perl]]よりも普及しています。
 
Pythonは1990年にグイド・ヴァンロッサムによって作られました。誰が書いても同じソースコードになるように(違う目的のコードは違う見た目になるように)設計されており、常に読みやすいプログラムを書くことができます。教育用プログラミング言語としても秀逸です。
 
== 文字列の書式化 ==
Pythonには、いくつかの異なる文字列の書式化の方法があります。
 
=== 書式化付き文字列化 ===
C言語の<code>sprintf()</code>に相当する書式付き文字列化は、Pythonでは文字列の % 演算子を使います。
また、書式化文字列に % によるフィールドが複数ある場合は、下のようにタプルを使います。
 
>>> print("%d.%d.%d" % (2, 6, 4))
2.6.4
 
=== 文字列の format メソッド ===
文字列の format メソッドを使う方法<ref>[https://peps.python.org/pep-3101/ PEP-3101]</ref>。
>>> print("{} {} {}".format(2, 6, 4))
2.6.4
 
=== f文字列 ===
PEP 498で新しく f文字列 が追加されました<ref>[https://peps.python.org/pep-498/ PEP-498]</ref>。
>>> print(f"{4} {9} {8}")
4 9 8
 
;文字列の書式化:<syntaxhighlight lang=python>
print("%d %d %d" % (0!=0, 0==0, 999))
print("{} {} {}".format(0!=0, 0==0, 999))
print(f"{0!=0} {0==0} {999}")
print(f"{abs(-123)} {2**10} {999}")
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
0 1 999
False True 999
False True 999
123 1024 999
</syntaxhighlight>
 
== pip ==
pipはPythonのパッケージインストーラーです<ref>{{Cite web
|url=https://pip.pypa.io/en/stable/
|title=pip documentation v21.3.1
|date=2021/12/20
accessdate=2021/12/20
}}
</ref>。Python Package Index<ref>{{Cite web
|url=https://pypi.org/
|title=The Python Package Index (PyPI) is a repository of software for the Python programming language.
|date=2021/12/20
accessdate=2021/12/20
}}
</ref> などのインデックスからパッケージをインストールするのに使用します。
 
pipがインストールされているかは、(インターラクティブ・モードではなく)コマンドラインから確認します。
;FreeBSD:<syntaxhighlight lang="shell">
% uname
FreeBSD
% pip -V
pip 22.1 from /usr/local/lib/python3.10/site-packages/pip (python 3.10)
</syntaxhighlight>
;Windows 10:<syntaxhighlight lang="powershell">
PS C:\Users\user1> pip.exe -V
pip 21.2.4 from C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2544.0_x64__qbz5n2kfra8p0\lib\site-packages\pip (python 3.9)
</syntaxhighlight>
;GNU/Linux:<syntaxhighlight lang="bash">
$ uname -a
Linux localhost 4.14.275-19064-g577a877aa35d #1 SMP PREEMPT Wed May 25 19:32:47 PDT 2022 x86_64 Intel(R) Celeron(R) N4020 CPU @ 1.10GHz GenuineIntel GNU/Linux
$ pip -V
pip 21.3.1 from /usr/local/lib/python3.10/site-packages/pip (python 3.10)
</syntaxhighlight>
 
 
== YAML ==
[[W:YAML|YAML]]は、構造化データやオブジェクトを文字列にシリアライズするためのデータ形式の一種です。
Pythonは、初期状態ではYAMLを利用できませんが、pyYaml <ref>https://github.com/yaml/pyyaml</ref>をインストールすることで、pythonでYAMLを処理できるようになります。
 
pipがインストール済みならば、
;コマンドライン:<syntaxhighlight lang="shell">
% sudo pip install pyyaml
</syntaxhighlight>
で pyYaml をインストールできます。
YAMLとPythonは別個の出自なのですが、YAMLはデータ構造をインデントで表し<ref>インデントでデータ構造を表すスタイルをブロックスタイルと呼びます。YAMLには他にフロースタイルと言う形式があり、これはYAML1.2からはJSONそのものです。[https://yaml.org/spec/1.2.2/ YAML Ain’t Markup Language (YAML™) version 1.2]</ref>、Pythonはプログラム構造をインデントをあらわすので似通った外観になります。
 
=== YAMLファイルの読出し ===
;test.yaml
<syntaxhighlight lang="yaml">
名前:
姓: 山田
名: 太郎
国籍: 日本
性別: 男
部活: 野球部
</syntaxhighlight>
;[https://paiza.io/projects/2WBoOy3Bw4tO5T22GxBPgA?language=python3 test-yaml.py]:<syntaxhighlight lang="python">
import yaml
 
with open('/workspace/test.yaml') as f:
obj = yaml.safe_load(f)
print(f"""\
{obj=}
{obj["国籍"]=}
{obj["名前"]["姓"]=}
""")
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="python">
obj={'名前': {'姓': '山田', '名': '太郎'}, '国籍': '日本', '性別': '男', '部活': '野球部'}
obj["国籍"]='日本'
obj["名前"]["姓"]='山田'
</syntaxhighlight>
: import で yaml をインポートする必要があります。
: pythonでYAMLのセミコロンのデータを読取った場合の辞書型のオブジェクトを返します
 
かつてYAMLの読取りには、yaml.load()が使われていましたが、セキュリティ上の懸念から deprecated となり、yaml.load() を使うと
Main.py:4: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
と警告されます。yaml.safe_load() を使いましょう。
{{See also|Python/ファイルの書き込みと読み込み#ファイルからの読込み}}
 
=== オブジェクトのYAMLへの変換 ===
;[https://paiza.io/projects/FXG1RvgSwy6InZ5_9su_RQ?language=python3 コード例]:<syntaxhighlight lang="python">
import yaml
obj = {
"a": [2,3,5,7],
"b": 3.14,
"c": "test test",
}
 
s = yaml.dump(obj)
print("*** Block style ***")
print(s);
print("*** Load ***")
print(yaml.safe_load(s))
s = yaml.dump(obj, default_flow_style=True)
print("*** Flow style ***")
print(s);
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="python">
*** Block style ***
a:
- 2
- 3
- 5
- 7
b: 3.14
c: test test
 
*** Load ***
{'a': [2, 3, 5, 7], 'b': 3.14, 'c': 'test test'}
*** Flow style ***
{a: [2, 3, 5, 7], b: 3.14, c: test test}
</syntaxhighlight>
 
=== YAMLファイルの書込み ===
;[https://paiza.io/projects/8h3tTkDUlddNCW87LwvHIg?language=python3 コード例]:<syntaxhighlight lang="python">
import yaml
 
obj = {
"a": [2,3,5,7],
"b": 3.14,
"c": "test test",
}
with open('/workspace/test.yaml', "w") as f:
yaml.dump(obj, f)
 
with open('/workspace/test.yaml') as f:
for s in f:
print(s, end='')
print("-"*40)
with open('/workspace/test.yaml') as f:
print(yaml.safe_load(f))
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="python">
a:
- 2
- 3
- 5
- 7
b: 3.14
c: test test
----------------------------------------
{'a': [2, 3, 5, 7], 'b': 3.14, 'c': 'test test'}
</syntaxhighlight>
{{See also|Python/ファイルの書き込みと読み込み}}
 
== pickle と marshal ==
pickleモジュールは、Pythonのオブジェクト構造をシリアル化およびデシリアル化するためのバイナリプロトコルを実装しています<ref>{{Cite web
|url=https://docs.python.org/3/library/pickle.html
|title= 3.10.0 Documentation » The Python Standard Library » Data Persistence » pickle — Python object serialization
|date=2021/12/02
|accessdate=2021/12/02
}}</ref>。
marshalモジュールも、Pythonのオブジェクト構造をシリアル化およびデシリアル化するためのバイナリプロトコルの実装ですが、将来に渡ってフォーマットを変えないことは保証されていないので、その用途にはpickleモジュールあるいはshelveモジュールを使ってください<ref>{{Cite web
|url=https://docs.python.org/3/library/marshal.html
|title= 3.10.0 Documentation » The Python Standard Library » Data Persistence » marshal — Internal Python object serialization
|date=2021/12/02
|accessdate=2021/12/02
}}</ref>。
marshalモジュールは、主に.pycファイルのPythonモジュールの "擬似コンパイル "コードの読み書きをサポートするために存在します。
 
;[https://paiza.io/projects/wg95etA69kFU0hJovyQm8Q?language=python3 コード例]:<syntaxhighlight lang="python">
import pickle
 
obj = [1,3,5,7]
obj.append(obj)
print(f'{obj=}')
 
pkl = pickle.dumps(obj)
print(f'{pkl=}')
print(f'{pickle.loads(pkl)=}')
 
import marshal
 
msl = marshal.dumps(obj)
print(f'{msl=}')
print(f'{marshal.loads(msl)=}')
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="python">
obj=[1, 3, 5, 7, [...]]
pkl=b'\x80\x04\x95\x0f\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x03K\x05K\x07h\x00e.'
pickle.loads(pkl)=[1, 3, 5, 7, [...]]
msl=b'\xdb\x05\x00\x00\x00\xe9\x01\x00\x00\x00\xe9\x03\x00\x00\x00\xe9\x05\x00\x00\x00\xe9\x07\x00\x00\x00r\x00\x00\x00\x00'
marshal.loads(msl)=[1, 3, 5, 7, [...]]
</syntaxhighlight>
 
== shelve ==
shelveモジュールは、永続的な辞書の実装です<ref>{{Cite web
|url=https://docs.python.org/3/library/shelve.html
|title= 3.10.0 Documentation » The Python Standard Library » Data Persistence » shelve — Python object persistence
|date=2021/12/02
|accessdate=2021/12/02
}}</ref>。
 
;[https://paiza.io/projects/wg95etA69kFU0hJovyQm8Q?language=python3 コード例]:<syntaxhighlight lang="python">
import shelve
 
filename = "/workspace/temp.shelve"
with shelve.open(filename) as sh:
sh['x'] = 1
sh['y'] = "abc"
sh['z'] = [0, 1, 2]
print(f'{sh["z"]=}')
 
with shelve.open(filename) as sh:
print(f'{ {k:v for k,v in sh.items()}=}')
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="python">
sh["z"]=[0, 1, 2]
{k:v for k,v in sh.items()}={'z': [0, 1, 2], 'x': 1, 'y': 'abc'}
</syntaxhighlight>
 
== 脚註 ==