====== Python ======
C#で作成したものをPythonに移植する上で調査したメモ\\
Visual Studio 2022を使用するも、途中で拡張機能が充実しているVisual Studio Codeに変更した。
===== Visual Studio関連 =====
==== Visual Studio上でUTF-8にして保存したい =====
Visual StudioでPythonファイルを保存するとShift-JISになりデバッグエラーになってしまう。\\
UTF-8で保存できるようにしたい。
* EditorConfig ファイルをプロジェクトに追加する
* EditorConfig ファイルの下記内容を記載
root = true
[*.py]
charset = utf-8
* [[https://docs.microsoft.com/ja-jp/visualstudio/ide/create-portable-custom-editor-options?view=vs-2022|EditorConfig で移植可能なカスタム エディター設定を作成する]]
* [[https://ja.stackoverflow.com/questions/85311/visual-studio-2022%E3%81%A7python%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92utf-8%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84|Visual Studio 2022でPythonファイルの文字コードをUTF-8にする方法を教えてください。]]
==== Visual Studioのエディターで行番号を表示する ====
Pythonはエラーに行番号が出てくるので表示するようにしておく。
[[https://docs.microsoft.com/ja-jp/visualstudio/ide/reference/how-to-display-line-numbers-in-the-editor?view=vs-2022|エディターで行番号を表示する]]
===== Visual Studio Code関連 =====
==== 環境構築 ====
* [[https://www.kkaneko.jp/tools/win/vscodepro.html|Visual Studio Code で Python プログラミング(Windows 上)]]
* [[https://note.kiriukun.com/entry/20220226-creating-python-project-with-windows-and-vscode-pipenv|Windows + VSCode + pipenv でPythonの開発環境を作る]]
==== 拡張機能 ====
[[https://yurupro.cloud/767/|【2022年最新版】VSCodeをPython超特化型にする、最高の拡張機能20選まとめ。 【VisualStudio Code】【プラグイン】]]
下記の拡張機能をインストール
* indent-rainbow
* ZenKaku
* Trailing Spaces
* Python Indent
* Python Docstring Generator
===== コーディング関連 =====
==== コーディング規約 ====
PEP(Python Enhancement Proposal)の中で、PEP 8は「Style Guide for Python Code」と銘打ち、Pythonのコードを記述する際の基本的なコーディングスタイルを定めている。
* [[https://qiita.com/naomi7325/items/4eb1d2a40277361e898b|Python命名規則一覧]]
* [[https://atmarkit.itmedia.co.jp/ait/articles/1912/10/news045.html|[Python入門]Pythonコーディングスタイルガイド]]
==== main関数の書き方 ====
Pythonはスクリプトなのでmain関数を定義する必要はありません。慣例的にmain関数を定義することがあります。
import sys
def main(argv):
print('Hello, World!')
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))
[[https://yu-nix.com/blog/2021/6/25/python-main/|Pythonのmain関数の書き方をわかりやすく解説]]
==== fromやimportの基礎 ====
[[https://techacademy.jp/magazine/23818|Pythonのfromやimportの基礎を現役エンジニアが解説【初心者向け】]]
==== コメント記載方法 ====
Google Styleを採用
[[https://zenn.dev/sasano8/scraps/806b614ca8f640|Python docstringについて]]
def func_google(param1, param2):
"""Summary line.
Extended description of function.
Args:
param1 (int): Description of param1
param2 (str): Description of param2
Returns:
bool: Description of return value
"""
return True
==== 定義変数 ====
Python には、C/C++ の const のような、定数を定義するためのキーワードは用意されていません。
Constクラスを作成して、その中でメンバ変数として定義する。重複定義とか気にせず単純にした。\\
定義変数は、英大文字を使用する。\\
* [[https://qiita.com/nadu_festival/items/c507542c11fc0ff32529|Pythonで定数を宣言したい(n+1番煎じ)]]
* [[https://maku77.github.io/python/syntax/const.html|Python で定数を定義する]]
class Const():
# クラス変数として定数を定義する
FOO = 1
BAR = "TEST"
使用方法
From Const import Const
a = Const.Foo
==== 文字列の囲み ====
Python では、単一引用符 ' で囲まれた文字列と、二重引用符 " で囲まれた文字列は同じです。\\
PEP 8では、どちらを推奨するかの立場は示しません。
C#からの移植なので、二重引用符(ダブルクォーテーション)をベースとする。
=== 文字列の長さ取得 ===
C#の用に文字列のメソッドになっていない。
✕ "abc".Length
◯ len("abc")
[[https://methane.hatenablog.jp/entry/20090702/1246556675|len が関数になっている理由]]
==== switch case文はない ====
Pythonにswitch文が実装されない理由として、公式ドキュメントには以下のように記述されています。
>if… elif… elif… else の繰り返しで簡単に同じことができます。switch 文の構文に関する提案がいくつかありましたが、範囲判定をするべきか、あるいはどのようにするべきかについての合意は (まだ) 得られていません。
[[https://docs.python.org/ja/3/faq/design.html?highlight=switch%23why-isn-t-there-a-switch-or-case-statement-in-python#why-isn-t-there-a-switch-or-case-statement-in-python|Python に switch や case 文がないのはなぜですか?]]
If文を駆使することで同様の処理が行えるため、議論こそあったようですが実装はされなかったようです。\\
しかし、Python3.10からはswitch文と同様の構文の「match文」が導入されます。
[[https://camp.trainocate.co.jp/magazine/python-switch-case/|Pythonでswitch/case文がない理由は?代用方法を解説!]]
==== フォーマット書式 ====
line = "{0}さんの身長は{1}cmです。{0}さんの体重は{2}kgです。".format("山田", 190, 105.3)
print(line)
# 山田さんの身長は190cmです。山田さんの体重は105.3kgです。
単純に左から順に一対一になっている場合は、以下のようにインデックス番号を省略できます。
line = "{}さんの身長は{}cmです。{}さんの体重は{}kgです。".format("山田", 190, 105.3)
print(line)
# 山田さんの身長は190cmです。山田さんの体重は105.3kgです。
[[https://gammasoft.jp/blog/python-string-format/|Pythonの文字列フォーマット(formatメソッドの使い方)]]
=== 日付書式 ===
代表的なものがこちらです。より詳しい情報は[[https://docs.python.org/ja/3/library/datetime.html#strftime-and-strptime-behavior|公式ドキュメント]]を確認してください。
* %Y: 年(4桁)
* %y: 年(2桁)
* %m: 月
* %d: 日
* %H: 時
* %M: 分
* %S: 秒
* %f: マイクロ秒
* %A: 曜日
* %a: 曜日(短縮形)
* %w: 曜日(数値: 0-6, 0:日曜日, 1:月曜日, … 6:土曜日)
import datetime
dt = datetime.datetime.today() # ローカルな現在の日付と時刻を取得
print(dt) # 2021-10-29 15:58:08.356501
[[https://atmarkit.itmedia.co.jp/ait/articles/2111/09/news015.html|[解決!Python]日付や時刻をYYMMDDhhmmssなどの形式に書式化するには]]
=== ミリ秒 ===
%fはマイクロ秒なのでミリ秒にする。
from datetime import datetime
date_s = (datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
print(date_s) # 2021-01-23 03:00:29.052
[[https://www.delftstack.com/ja/howto/python/python-datetime-milliseconds/|Python で DateTime をミリ秒単位の文字列に変換する]]
==== 例外処理 ====
* [[https://note.nkmk.me/python-try-except-else-finally/|Pythonの例外処理(try, except, else, finally)]]
* [[https://qiita.com/qqhann/items/5dbe38be94bd44b20937|Pythonの例外処理で例外の内容を知る]]
=== 例外を発生させる ===
自作の例外を発生させるraiseの使い方
* [[https://uxmilk.jp/39845|Pythonで例外を発生させる:raise]]
* [[https://www.delftstack.com/ja/howto/python/manually-raise-exceptions-in-python/|Python で手動で例外を発生させる]]
* [[https://techacademy.jp/magazine/22124|Pythonで自作の例外を発生させるraiseの使い方を現役エンジニアが解説【初心者向け】]]
=== catchした例外をそのまま親まで届ける ===
[[https://teratail.com/questions/292576|【python/例外処理】 catchした例外をそのまま親まで届ける方法はありますか?]]
式を伴わなければ、 raise は現在のスコープで最終的に有効になっている例外を再送出します。
try:
...
except Exception as e:
raise
そもそもraiseには例外インスタンスが渡せるので
try:
...
except Exception as e:
raise e # ★
でもいいです。こちらだとTracebackに★の行の情報が加えられます。
except節の中でifの分岐などでraiseが2箇所以上現れるならこちらで。
==== 配列およびリスト処理 ====
* [[https://note.nkmk.me/python-split-strip-list-join/|Python, splitでカンマ区切り文字列を分割、空白を削除しリスト化]]
* [[https://pyhoo.jp/python-list-change|Python list(リスト)の変更|追加・並替・更新など]]
* [[https://note.nkmk.me/python-copy-deepcopy/|Pythonの浅いコピーと深いコピー: copy(), deepcopy()]]
==== クラス内のメソッドを別のメソッド内で呼ぶ ====
クラス内のメソッドを別のメソッド内で呼ぶと「name 'xxx' is not defined」エラーになる。\\
関数の順序は関係ない、クラス内のメソッドの第1引数は必ずselfを付け、self.xxx で呼び出す必要があった。
Pythonではメソッドの第一引数は「self」が必須であり、自身のクラスのインスタンスを受け取るとコーディング規約で決まっているらしい。\\
>Pythonのメソッド引数に書く「self」はしばしば,他言語からのPython移民を中心に「ウザイ」「キモイ」「消えてなくなれ」と攻撃の対象となることが多いのです。
>https://coreblog.org/ats/translation-of-why-explicit-self-has-to-stay/
* [[https://teratail.com/questions/138900|pythonでのクラス内のメソッドを別のメソッド内で使う方法]]
* [[https://python.ms/self/|なんで self を書かないといけないの?]]
* [[https://qiita.com/DataBridge/items/2580522199e407abd8df|Python3のメソッド(第一引数にself必須)とスタティックメソッド(引数不要)の違いを検証してみた]]
* [[https://qiita.com/yaboxi_/items/70249bd5a977d614aa4c|Pythonにおける「self.クラス変数」でのクラス変数・インスタンス変数の参照順]]
===== 自作クラスで'module' object is not callable エラー =====
原因はimportの書き方が間違っているから\\
以下の書き方だとエラーになる。
import myClass
myInstance = myClass()
下の書き方に修正すると動く。
from (myClassのファイル名) import myClass
myInstance = myClass()
[[http://mynetabook.blogspot.com/2018/10/importtypeerror-module-object-is-not.html|[トラブル] 自作クラスのimport時にTypeError: 'module' object is not callableになる]]
===== コマンドライン引数の処理 =====
[[https://atmarkit.itmedia.co.jp/ait/articles/2112/21/news025.html|[解決!Python]Pythonスクリプトに与えられたコマンドライン引数を処理するには]]
===== ファイル関連 =====
==== パス操作 ====
import os
filepath = r"C:\temp\Image.bmp"
# ファイル名 os.path.basename()
print(os.path.basename(filepath)) # 'Image.bmp'
# フォルダ名 os.path.dirname()
print(os.path.dirname(filepath)) # 'C:\temp'
# 拡張子の取得 os.path.splitext()
print(os.path.splitext(filepath)[1]) # '.bmp'
# 拡張子なしのパス os.path.splitext()
print(os.path.splitext(filepath)[0]) # 'C:\temp\Image'
# 拡張子なしのファイル名 os.path.basename(), os.path.splitext()
print(os.path.splitext(os.path.basename(filepath))[0]) # 'Image'
# ルートディレクトリ os.path.splitdrive()
print(os.path.splitdrive(filepath)[0]) # 'C:'
[[https://imagingsolution.net/program/python/python-basic/get_file_name_extension_etc/|【Python/os】パスからファイル名、拡張子、フォルダ名などを取得する]]
==== ファイル読み書き ====
[[https://atmarkit.itmedia.co.jp/ait/articles/2104/27/news021.html|[解決!Python]エンコーディングを指定して、シフトJISなどのファイルを読み書きするには]]
==== フォルダ未存在時作成 ====
フォルダ名は、フルパスで指定すればいい。
import os
new_path = "demo_folder"
if not os.path.exists(new_path):
os.mkdir(new_path)
[[https://qiita.com/yusa0827/items/b70780c7ee38a8282375|Python フォルダの作成 既存かチェックあり]]
===== HTTP クライアント =====
urllibライブラリーを使用する。
* [[https://qiita.com/hoto17296/items/8fcf55cc6cd823a18217|Python の HTTP クライアントは urllib.request で十分]]
* [[https://atmarkit.itmedia.co.jp/ait/articles/1910/15/news018.html|[Python入門]urllib.requestモジュールによるWebページの取得]]
* [[https://docs.python.org/ja/3/howto/urllib2.html|urllib パッケージを使ってインターネット上のリソースを取得するには]]
* [[https://dev.classmethod.jp/articles/python-urllib-examples/|urllibだけである程度HTTPリクエストを頑張る]]