2 + "2" = ?
動的型付けの言語では、数値と文字列とを足そうとしたときの挙動は言語毎に異なる。今回、Perl、Python、JavaScriptにおける文字列と数値とを足したときの挙動を比較した。
Python
print("2" + "2") print(2 + "2")
数値と文字列との演算はできないとインタプリンタが拒絶する結果に。
22 Traceback (most recent call last): File "test.py", line 2, in <module> print(2 + "2") TypeError: unsupported operand type(s) for +: 'int' and 'str'
まとめ
各言語の設計思想?がよく現れている気がする。Rubyの実行環境はないので今回は省略。
Djangoで外部キーを設定したときのフィールド表示
admin画面での外部キーの表示
下記の様に外部キーを設定して、admin.pyに各モデルを登録して、Djangoのadmin画面でモデルを管理するときの外部キーの表示方法について。Orderモデルのuser_idキー(外部キー)の表示は、参照元たるPaymentUserのstr()に依存することに注意。このstr()がないと、「PaymentUser Object」の様に表示され、どの様な値が入って居るのか全く判らなくなる。
class PaymentUser(models.Model) : user_id = models.IntegerField(primary_key=True) username =models.CharField(max_length=100) def __str__(self): return u'%s' % (self.user_id) class Order(models.Model) : order_id=models.IntegerField(primary_key=True) user_id=models.ForeignKey(PaymentUser) amount=models.IntegerField()
以下にstr()の有無で表示がどう変化するか比較画像をあげた。
str()が定義されて居ないと、オブジェクト名だけの表示となる
str()が定義された場合の外部キーの表示
参照元
The Django admin site | Django documentation | Django
上記リンク先に「A few special cases to note about list_display:」なる但し書きがあって、
If the field is a ForeignKey, Django will display the str() (unicode() on Python 2) of the related object.
とある。
ファイルバッファの強制フラッシュ(Python)
ファイルの書き出し処理といっても直ちにディスクにそのファイルが書き出されるわけではない。ディスクへの書き出しが遅れうるという挙動を失念して居て、以下のコードで意図通りの動作にならず困ったことがあった。
with codecs.open('filename', 'w', 'UTF-8') as file : file.write(body) subprocess.call('cmd filename', shell=False)
「あるファイルを事前に書き出して、事前出力したファイルを入力として外部プログラムが諸々の処理をする」という単純なコードだ。しかしながら、場合によっては、subprocess.call()の時点で入力となるべきファイルが空ファイルの可能性もあり、意図通りの動作にならないのである。
ディスクへの書き出しは直ちに実行されない
ファイルの書き出し処理とはいっても、Pythonインタプリンタはデータをファイルバッファに渡したら次の処理に進んでしまう。ファイルのclose処理がされた時点でもディスク上に実体がある保証はない。ファイルの中身が依然としてバッファに格納されたままで、ディスク上は空ファイルのままのこともある。このバッファがいつ書き出されるかはインタプリンタの制御下にあり、最遅としてプロセス終了時に漸くディスクへの書き出しが始まることもある。
しかし、後続の処理がそのファイルを用いなければならないときは、ディスク上にファイルがしっかりと書き出されていないと非常に困る訣である。
flush()メソッドの登場
以下の様に一行だけ追加すれば上述の事態は避けられる。flsuh()によりバッファ上の内容は直ちにディスクに書き出されるので、後続の処理で問題が起きることはない。
with codecs.open('filename', 'w', 'UTF-8') as file : file.write(body) file.flush() subprocess.call('cmd filename', shell=False)
参考リンク
同様の事例は標準出力でも起きうるので、sys.stdout.flush()というメソッドが用意されて居る。
Wkhtmltopdfで指定サイズより小さく出力されるときの対処法
HTMLをPDFに変換してくれるオープンソースライブラリWkhtmltopdfがある。オープンソースな上にクロスプラットフォームという優れもののライブラリだ。ただ、これによって出力されたPDFで、フォントサイズやボックスサイズなどが指定より小さく出力されることがある。大凡、指定の90パーセント程度に縮小されるのである。A4判程度ならこの差はなかなか気が付かないが、A0といった大判出力では相当の絶対誤差となって出てくる。今回はそれの対処法について書こう。
原因はwebkitのレンダリング
Wkhtmltopdfはレンダリングエンジンwebkitを使っているが、このwebkitにはpixel/inch ratioを自動調整する機能がある。元々は種々のデバイス解像度に対応するためのものらしいが、これが悪さをするらしい。通常のCSSでは96[pixel/inch]であるが、この値を前提に厳密な位置指定をして居る状態でpixel/inchを弄られると当然おかしな出力になる。
オプションで回避。
上記の事態を避けるためには、PDF出力時に--disable-smart-shrinkingオプションを付ければよい。このオプションは公式では次の様に説明されて居る。
Disable the intelligent shrinking strategy used by WebKit that makes the pixel/dpi ratio none constant
さて、下記の様にオプションを付けると大体意図通りの大きさで出力された。
$ wkhtmktopdf --disable-smart-shrinking input output
最初はCSSの記述ミスかと思って居たが、調べてみたらライブラリのお節介な調節機能の所為だったという落ち。
属性の併記時におけるCSSのnth-of-typeの挙動
CSSのセレクタとしてnth-of-typeがある。指定した番目の要素に対してCSSを適用できる便利なものである。別段難しいセレクタではない様に見えるが、属性が併記されたときに案外勘違いしやすい挙動になって居るので、今回はそれについて書きたい。
nth-of-typeの挙動の確認
最初にCSSの入門サイトでよく見られる様な記述でnth-of-typeの挙動を確認する。
<style type="text/css"> li:nth-of-type(2) { color : red; } </style> <ul> <li>ネオサイタマ炎上</p> <li>キルゾーン・スモトリ</p> <li>キョート殺伐都市</p> </ul>
これをブラウザで表示すると下記の様になる。予想通り「キルゾーン・スモトリ」の文字が赤くなった。
属性が併記されたとき
それでは次の場合はどうだろう。先程と違ってクラス名にtitleを指定した。
<style type="text/css"> li.title:nth-of-type(2) { color : red; } </style> <ul> <li>ネオサイタマ炎上</p> <li class="title">キルゾーン・スモトリ</p> <li class="title">キョート殺伐都市</p> </ul>
これをブラウザで表示するとどの様に表示されるだろうか?――結果としては以下の様になる。先程と全く同じであり「キョート殺伐都市」の文字は決して赤くならない。
仕様通りの挙動!
これは決してバグではなく書いた通りの動きである。nth-of-typeの仕様を理解して居ないと勘違いしやすいのだが、属性が併記されたときnth-of-typeは次の手順を取る。一例として、element_name.class:nth-of-type(n)とあった場合、
- classやidが指定されて居ても、最初はelement_name:nth-of-type(n)として動作する。
- element_name:nth-of-type(n)にそのclassやidが指定されて居たら、そのCSSが適用される。
つまり、上述の例で説明すると先の記述は「2番目のli.titleに対するCSS」を意味するのではなく、「2番目のliで、かつtitleクラスが指定されたときに対するCSS」を意味するのである。
他サイトを見るとnth-of-typeの例はどれも要素名だけの場合で解説して居ることが多いが、属性も併記された場合など少し複雑な事例に対する説明は見かけない様な気がする。何れにせよ、CSSも思った通りに動くのではなく、書いた通りに動くことに変りはない。