Python関連

聖根のアジト / メモ / プログラミングメモ / Python関連



related_nameとsetとannotate

Djangoでモデルの逆参照のための名称を手動で指定する際、related_nameを用いるが、 これを利用するには注意点がある。
例えば、逆参照先が多であり、名前がTestModelの場合、testmodel_setという形で逆参照ができるが、 annotateでの指定の中では単に"testmodel"となる。

これに対し、例えば

related_name="test_model_set"

とすると、test_model_setという形で逆参照ができるが、 annotateでの指定の中でも"test_model_set"と、_setを付けねばならなくなる。
逆に

related_name="test_model"

としたならば、annotateでの指定の中でも"test_model"で良くなるが、 逆参照の際にも単にtest_modelでなくてはならなくなる。

つまり、本来違う名前だったものが、related_nameを使うだけで、同一の名前に強制的になってしまう。
これでは不都合な事も多いのではないかと思う。

対処としては、

related_name="test_model_set"

に加えて、

related_query_name="test_model"

を指定すれば、test_model_setという形で逆参照が可能なまま、 annotateでの指定の中では単に"test_model"でよくなる。

ついでに、データベース上のテーブル名も変える場合は、以上に加えて、Metaの所に

db_table="テーブル名"

という形で指定する。
ただ、通常テーブル名は「アプリ名_モデル名の小文字」
となっている、例えばアプリ名がtest_appならば、今回の例ではtest_app_testmodelという名前になる所が、
db_table="test_model"

とすると、単に「test_model」という名前となってしまう。

他の自動的に命名されたテーブルと命名規則を合わせるならば、

db_table="test_app_test_model"

とせねばならないが、後からアプリ名変えたいなんて時には、 該当する箇所を全て書き換える必要が出て、少々スマートでないと思う。
%(app_label)sを利用した方法では上手く行かなかった。
makemigrationの段階では、ちゃんとアプリ名に変換してくれないようだ。
ひとまず、appsで定義されているアプリ名を利用する形ならば上手く動作したが、これで良いのかはわからない。

2021.5.23


PythonはJavaScriptと違って多重継承できるようだが、 基底クラスのコンストラクタは最初に継承したものしか実行されないっぽい。
コンストラクタもオーバーライド扱いになってしまうというわけかな。
折角多重継承ができても、これでは有難味が薄いかな…。
C++の場合、コンストラクタはクラス名と同じ名前だから、 必然的にオーバーライドにはならないし、自動的に実行されるが。
C++よりも融通が利くはずのスクリプト言語にこんな落とし穴があるとは。
特別な事情が無い限りは、メンバオブジェクト……いや、プロパティっていうのか、 として、基底にしようとしたクラスのインスタンスを作った方が良さげかな。

あと、クラス一般の話だが、メソッドの引数にいちいちselfを取る必要があるのが、 JavaScriptやC++に比べて面倒くちゃい所だと思う。
クラスメソッドとの兼ね合いもあるのかもしれんが。

2021.4.11


循環import

Pythonは循環importってのが厄介だ(Pythonに限らないかもしれないが)。
互いに一部の関数だけをimportしたいだけで引っかかってしまうのが辛い。
Cの場合なら、宣言をヘッダに記述したり、プリプロセッサでのインポート済み判定を
利用して、回避ができるが、Pythonでimport済み判定を行おうとしたら、 import済みのはずなのにimportしたはずのものが定義されてないという事態に。

ただ、ローカルスコープ内でimportした場合、循環import扱いとならない場合もあるようで、 これによってある程度は回避できそうだ。

2021.4.11


複数行コメントアウト

Pythonでは複数行をまとめてコメントアウトする場合に、 三重のダブルまたはシングルコーテーションが使われてるが、 これらは文字列という扱いでもあるから、 リストの定義の中などで用いるとエラーや不具合が起こってしまうのが難点。
普通の複数行コメントアウトも有ると有難いんだけどなぁ……。
一応、vscodeの場合ならば、「Ctrl+K」→「Ctrl+C」で単行のコメントアウトを複数行まとめて行う事が、 そして「Ctrl+K」→「Ctrl+U」でコメントアウト解除ができるようだ。

2021.4.11


Pythonを勉強しているが、配列をリストとタプルに分ける意義がよくわからない。
タプルはリストの定数版のように解釈してるが、 [6, 8] == (6, 8)が偽になるのは地味に不便ではないか。
そして、集合(set)には定数版たるfrozensetが用意されており、 こちらは{6, 8} == frozenset({6, 8})が真となる。
また、バージョンにもよるかもしれないが、辞書(dict)にはなぜ定数版が無いのか。

集合の要素にはタプルや凍結集合は指定できても、変更が可能であるリストや通常の集合は指定できないが、 タプルの要素としてはリストも集合も指定でき、各要素に対する変更も反映されるというのも謎。

2021.3.27