見出し画像

Retro-gaming and so on

酷い模擬試験を見た

Python 3 エンジニア認定基礎試験なるものがあるらしい。PythonEDなる勃起不全を起こしそうな名前の団体(※1)が提供してるようだが、良く知らん(※2)。
全く興味が無かったのだが、件のサイトに関連企業で無料の模擬試験が受けられる、とか書いてたので洒落で覗いてみる事にした。



当然暇つぶしなんで、取り敢えずトップのプライム・ストラテジーなる、これまた良く分からん会社の模試、なるものを受けてみる事とした。
・・・・・・しかしやっていくうちに愕然としたモノとなる。
うん、あんま酷いんで、スクショ撮っておいたんだけど。これだ。



(そもそも、「計算」はcalculationなのにcalcの筈がculcになってる、ってのは置いておいて)さて、これの解は一体どれなんだろう。僕も一瞬「ん?」って思った。
実はこの解は上から4番目になる。
え、ウソ?って思うだろ?そう思うのは正しい。一応、Pythonチュートリアルにも書いてるが、しかし、どっちかっつーと、これはバグじみた挙動だ。
何度か指摘してるが、Pythonはスコープの管理なんかが割と雑で、通常、関数が別の引数を用いて再実行されると全ての値がリセットされるんだが、Pythonの場合は、デフォルト引数がリストや辞書型の場合、あたかも大域変数のような動きを見せる
ハッキリ言うと、この辺のPythonの実装は間違ってるんだ。

例えばRacketで同様のコードを書いてみよう。

(define (calc a (b 1) (squares '()) (cubes '()))
 (set! squares `(,@squares ,(* a a))) 
 (set! cubes `(,@cubes ,(* b b b)))
 `(,squares ,cubes))

(display (calc 1))
(display (calc 2 3))
(display (calc 3 4))
(display (calc 4 5))

当然結果は次のようになる。

((1) (1))((4) (27))((9) (64))((16) (125))

各実行毎にデフォルト引数に束縛されたリストは更新される。前に使った値は当然残らないのだ。当たり前だ。
これは別にRacketに限った話ではなく、マトモなレキシカルスコープを持ってるプログラミング言語だと当たり前の挙動なんだ。


// JavaScript の場合

function calc(a, b = 1, squares = [], cubes=[]) {
 squares.push(Math.pow(a, 2));
 cubes.push(Math.pow(b, 3));
 return [squares, cubes];
}

console.log(calc(1))
console.log(calc(2, 3))
console.log(calc(3, 4))
console.log(calc(4, 5))

ところがPythonだとマトモな実装が成されていない
ぶっちゃけると、まず、Pythonチュートリアルはプログラミングが初めて、って人に向けては書かれてないわけで、そして丁寧に書いてはいるが、一方ヘナチョコな実装で「フツーのプログラミング言語であり得ない挙動をする」事に気づいたプログラミング経験者に対してドキュメントで言い訳してるってのがホントのトコなんだ(笑)。
だって、こう考えてみれば良い。果たして、デフォルト引数がリストや辞書型だった場合、関数の再呼び出しにも関わらず内部に値が残ってる事に一体どんな得があるんだ?と。
こんなバカな実装は、フツーは無いのだ。そしてPythonは正直、ちょくちょくそういうバカな実装を行っている(※3)。

さて、こんなバカな実装に対する問題を出すなんて、ロクな判断じゃない、って事は分かるだろう(笑)。クソ問題だ(笑)。お陰さんで気持ちがヘナヘナになっちまった。要するにやる気が全く無くなった、って事だな(※4)。
まぁ、これはあくまで模試なんだけど、本試験がこのレベルの出題をするのなら、こんな資格試験を受けても意味がない、って言わせてもらおう。どうせこんな試験を突破した奴らはPythonでクソコードを量産する事に勤しむ、なんつーのが目に見えてる。それをPythonic、とか言ってんだろ(笑)。
まぁ、既に第一問目から「Pythonはインタプリタだ」とか書いてるんでダメ臭はプンプンしてたけどな。

※1: トップページの写真を見るともはやしなだれたチンコ2本、にしか見えない(謎



※2: ちなみにだが、「☓☓協会」と言う名称が付くと、如何にも公益団体だ、って印象を持ちかねないが、これは印象操作であって、「☓☓協会」と名乗ってるから、と言って「営利目的ではありません」と言う意味ではない。
重要なのは「一般社団法人と言う部分で、利益の分配規則が株式会社とは違うが、それ以外は株式会社に準じてる、と考えた方が良い。別に公益の為に活動してるわけじゃなくってその団体の利益の為に活動してるんだ。
別に利益の為に活動してるのを批判してるんじゃない。ただし、上にも書いたが、「☓☓協会」とか名付けてると如何にも公益の為に活動してる、って勘違いする輩が多いので、釘を刺してるだけだ。
そして公益の為に活動してるわけではない、と言う事は翻ってみると国等の管理が入らない言い換えると、ここが実施している資格試験をパスしたから、と言っても何の保証にもならないのである。
これは国が施してる情報処理技術者試験と言う国家資格とは全く別物だ(ハッキリ言えば権威がない)、と言う事を覚えておこう。

※3: Pythonチュートリアルに拠ると、要するにこういうバグ染みた挙動を避ける為には、デフォルト引数にリストや辞書を使うのは止めて、Noneを与えろ、と言うような話が書いてある。

def culc(a, b = 1, squares=None, cubes=None):
 squares = [a**2]
 cubes = [b**3]
 return squares, cubes

こうすれば、フツーのマトモなスコープを持った言語のように動く、と言う事だ。
繰り返すが、こうやってPythonは実装のマズさをドキュメンテーションでカバーするのである(笑)。
Pythonが信用しきれない、ってのはこういう辺りだ。

なお、破壊的変更を避けて

def culc(a, b = 1, squares = [], cubes = []):
 return squares + [a**2], cubes + [b**3]

とするのも良いだろう。
と言うか、何度か書いてるが、比較すると、Pythonのリストのappendメソッドが如何に危険か、と言う事が分かるだろう。
逆に言うと、そういう危険な行為に対して無自覚に出題してる辺りが、この模試がダメなトコだし、また、同じレベルだとしたら、この資格認定試験はとてつもなくダメな試験だ、と言う事になる。
こんな出題のプログラムはトリビアルだし書くべきじゃあないんだ。

※4: 途中で全然やる気がなくなり、そもそも全く準備をしてなかったのに75点取れてしまった。合格ラインが70点以上、っつーんで、ヤバい、俺様もPythonでクソコードを生産出来るPythonicな資格がある(可能性がある)、って事になってしまった(笑)。
冗談じゃねぇぞ(苦笑)。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「プログラミング」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事