Slide 1

Slide 1 text

エムスリー流! 難読クイズを作ってPythonの 深淵に触れるコツ! 2024/10/17 技育CAMPアカデミア エムスリー株式会社 VPoE 河合俊典

Slide 2

Slide 2 text

こんにちは これからの”ギーク”を担う皆様

Slide 3

Slide 3 text

3 000_0&00^00-0x0_0_00^0o0_00-~0^-0b0_0_0 以下のPythonスクリプトの実行結果は? ① 0 ② 1 ③ “M3” ④ SyntaxError

Slide 4

Slide 4 text

000_0&00^00-0x0_0_00^0o0_00-~0^-0b0_0_0 正解は ② 1

Slide 5

Slide 5 text

分解して見てみよう 000_0&00^00-0x0_0_00^0o0_00-~0^-0b0_0_0

Slide 6

Slide 6 text

分解して見てみよう 000_0&00^00-0x0_0_00^0o0_00-~0^-0b0_0_0 算術演算子、ビット演算子の2種類が見えますね

Slide 7

Slide 7 text

Pythonは可読性のために数値にアンダースコアを挟める print( 100_00_00_0 ) # 10000000 C++では ‘ (シングルクォーテーション) RubyやGo、JavaScript等の言語では _

Slide 8

Slide 8 text

数値には接頭辞を付ける事ができる print( 1000 ) # 10進数 print( 0b10 ) # 2進数 binary print( 0o10 ) # 8進数 octal print( 0x10 ) # 16進数 hexadecimal print( 0000 ) # 0 print( 0001 ) # SyntaxError 前のアンダースコアも合わせて こういった数値の記法は整数リテラル(integer literal)と呼ばれる機能の1つ 多くの言語で実装されている

Slide 9

Slide 9 text

分解して見てみよう 000_0&00^00-0x0_0_00^0o0_00-~0^-0b0_0_0 0 & 0 ^ 0 - 0 ^ 0 - ~0 ^ -0 16進数の0 8進数の0 2進数の0

Slide 10

Slide 10 text

算術/ビット演算子を振り返り print( 1 - 1 ) # 0 print( 1 & 0 ) # 0 AND演算子 print( ~0 ) # -1 NOT演算子 => -(x+1) print( 0 ^ 1 ) # 1 XOR演算子 ビット演算子は難読化では必修 特にNOTは実質的に -(x+1) として扱えるので難読化で便利

Slide 11

Slide 11 text

0 & 0 ^ 0 - 0 ^ 0 - ~ 0 ^ -0 0 - 0 - ~ 0 0 - 0 - -1 1 AND、XORが優先的に処理される ast.parseしてみよう!

Slide 12

Slide 12 text

000_0&00^00-0x0_0_00^0o0_00-~0^-0b0_0_0 正解は ② 1

Slide 13

Slide 13 text

完全に理解した!🤪

Slide 14

Slide 14 text

申し遅れました 河合(@vaaaaanquish) エムスリー株式会社 VPoE PIVOT株式会社 技術顧問 高専 → 大学 → Sansan/Yahoo!/CADDi → M3 Google Cloud Champion Innovator (AI/ML) MLコンテスト入賞、書籍執筆、podcast devsumi、Google Cloud Next等で登壇

Slide 15

Slide 15 text

15 エムスリー株式会社 知ってますか?

Slide 16

Slide 16 text

患者コミュニティ 医師の9割が登録するPF 東証プライム上場、時価総額1兆円超 医療分野で30以上のプロダクト、100以上の事業を作っています 16 Q&Aオンライン診断 画像/音声/電気信号で診断AI 日本No.1の電子カルテ toC/toBな病院DXアプリ

Slide 17

Slide 17 text

超少数精鋭エンジニア 100人体制! あらゆる技術の知識を活かし イノベーションを創出する ギークの登竜門 ISUCON 2023入賞 日本IT団体連盟 CYBER INDEX認定 GoodDesign賞受賞 技術書典 最新刊完売 国際ジャーナル1st 書籍執筆経験者多数 テックブログ年100記事以上 社内LT250回、輪読会、開発合宿 300 Star超えのOSS

Slide 18

Slide 18 text

18 @m3_engineering で待っています

Slide 19

Slide 19 text

という訳で 今日は”ギーク”を育てるべく来ました

Slide 20

Slide 20 text

なぜ難読クイズをやるのか?

Slide 21

Slide 21 text

伝統的なギークカルチャー for i in range(10):print(i%3//2*"Fizz"+i%5//4*"Buzz"or-~i) Code Golf 可能な限り短いコードで特定の アルゴリズムを記述する ショートコーディング等とも呼ばれる コンテストサイトがあったり コードゴルフなプログラミング言語も存在する 難読化(Obfuscation) コード自体のエレガントさを競う C言語の難読化を行う IOCCC* があったり Perl難読化の O bfuscated Perl Contestがある RubyKaigiではTRICK*が開催されている * The International Obfuscated C Code Contest (IOCCC) * Transcendental Ruby Imbroglio Contest for rubyKaigi (TRICK) TRICK 2018 年度の入賞作品 (Jan Lelis) Grass言語で書かれた Hello world 世界で一番短い PythonのFizzBuzz

Slide 22

Slide 22 text

伝統的なギークカルチャー Quine 実行した結果がソースコードと同じになる ように記述する遊び Quineといえば遠藤さん みたいな方が書いた本 こちらの訳者は エムスリーのGM

Slide 23

Slide 23 text

Innovatorにとって”遊び”は守破離の源泉 エンジニアリングの型を学ぶ事は非常に重要 その先、世界に影響を与えられるInnovator、 真のGeekになるには、多くの型から学び 自信の中心となる”新しい型”を見出す必要がある > コンピュータの遊び方を知ろう

Slide 24

Slide 24 text

やっていき🚀

Slide 25

Slide 25 text

25 (d >_< b) if (c:=('ω')<"hi") else (c^0^c)-~3 以下のPythonスクリプトの実行結果は? ① “M3” ② 4 ③ 108 ④ True

Slide 26

Slide 26 text

(d >_< b) if (c:=('ω')<"hi") else (c^0^c)-~3 正解は ② 4

Slide 27

Slide 27 text

分解して見てみよう (d >_< b) if (c:=('ω')<"hi") else (c^0^c)-~3

Slide 28

Slide 28 text

分解して見てみよう if (c:=('ω')<"hi") : (d >_< b) else: (c^0^c)-~3

Slide 29

Slide 29 text

Assignment Expressions # 評価のタイミングで代入を行える演算子 print(x:=1) # 1 <- 評価結果は代入値になる print(x) # 1 他言語ではセイウチ演算子(walrus operator)と呼ばれる PEP 572を見ると「walrus operatorじゃないんでよろしく」的な文言が

Slide 30

Slide 30 text

分解して見てみよう if (c := ('ω')<"hi") : (d >_< b) else: (c^0^c)-~3 変数cに値を代入している (“ω”) と “hi” を比較した結果

Slide 31

Slide 31 text

Pythonのtuple print( (1, 2) ) # (1, 2) print( (1) ) # 1 print( (1, ) ) # (1, ) print( (((((1))))) ) # 1 括弧の末尾に , (カンマ) がある/ない で 評価結果が変わる

Slide 32

Slide 32 text

分解して見てみよう if (c := 'ω' < "hi") : (d >_< b) else: (c^0^c)-~3 (“ω”)は実質 ”ω” 文字列同士の比較は Unicodeコードポイントの比較 アルファベットがUnicode上で 前の方にある事を知っていると ここは False とわかる

Slide 33

Slide 33 text

分解して見てみよう if (c:=('ω')<"hi") : (d >_< b) else: (c^0^c)-~3 先程、Assignment Expressionsにより 変数cにはFalseが入っている

Slide 34

Slide 34 text

分解して見てみよう if (c:=('ω')<"hi") : (d >_< b) else: (0^0^0)-~3 さっき見たやつだ!

Slide 35

Slide 35 text

ビット演算子を振り返り print( 1 - 1 ) # 0 print( 1 & 0 ) # 0 AND演算子 print( ~0 ) # -1 NOT演算子 => -(x+1) print( 0 ^ 1 ) # 1 XOR演算子 ビット演算子は難読化では必修 特にNOTは実質的に -(x+1) として扱えるので難読化で便利

Slide 36

Slide 36 text

分解して見てみよう if (c:=('ω')<"hi") : (d >_< b) else: 0 - -4 0^0^0は当然0 ~3は-(x+1)に当てはめて-4 この算術の結果は 4

Slide 37

Slide 37 text

(d >_< b) if (c:=('ω')<"hi") else (c^0^c)-~3 正解は ② 4

Slide 38

Slide 38 text

ちなみに… if True : (d >_< b) else: (c^0^c)-~3 Traceback (most recent call last): File "", line 1, in NameError: name 'd' is not defined ここは評価時Errorなので構文として 成り立っていれば何でも良い場所! (d >_< b) if (c:=('ω')<"hi") else (c^0^c)-~3 を前から読もうとすると誤爆する🤪

Slide 39

Slide 39 text

39 ...is...is...is...is...is... 以下のPythonスクリプトの実行結果は? ① ... ② 🤪 ③ False ④ True

Slide 40

Slide 40 text

...is...is...is...is...is... 正解は ④ True

Slide 41

Slide 41 text

Ellipsisオブジェクト # Ellipsisは省略表記のオブジェクトです print(...) # Ellipsis # numpyなどではよくスライス時に省略表記として使われます import numpy x = numpy.array([[1, 2], [3, 4]]) print(x[1, ...]) # [3, 4] # Ellipsisはbool値としてはTrueです print(bool(...)) # True # Ellipsisの比較もTrueになります print(...is...) # True GoやC++等では可変長引数や sliceのOperatorとして使われる

Slide 42

Slide 42 text

連続した比較演算子isは 同時に評価されるので 正解は ...is...is...is...is...is... ④ True

Slide 43

Slide 43 text

ちなみに… (...is...)is...is...is...is... これは False です 🤪

Slide 44

Slide 44 text

ちなみに… (...is...)is...is...is...is... 先に評価されTrueに True is ... は False 前から評価しようとすると誤爆する🤪

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

46 list(map(list,list(map(map,map(lambda map:list,map:='map'),map)))) 以下のPythonスクリプトの実行結果は? ① “map” ② [[['m']], [['a']], [['p']]] ③ [“map”, “list”] ④ [[[“m3”]]]

Slide 47

Slide 47 text

正解は ② [[['m']], [['a']], [['p']]] list(map(list,list(map(map,map(lambda map:list,map:='map'),map))))

Slide 48

Slide 48 text

分解して見てみよう list(map( list, list(map( map, map(lambda map:list, map:='map'), map )))) > どうやらlistとmapの挙動は知る必要がありそう

Slide 49

Slide 49 text

Pythonのmap # mapはiterableなオブジェクト全てに関数を適応します # 返り値はIteratorなのでlist function等を適応する必要があります map(str, [1, 2, 3]) # list(map(str, [1, 2, 3])) # ["1", "2", "3"] # mapの第一引数にlistを入れると第2引数のiteratorを回してlist化します list(map(list, '123')) # [["1"], ["2"], ["3"]] # mapの第2引数以降はzipのように扱えます # これを利用してmapの中にmapを書いてみます map(map, [list,list,list], "abc") # 実質 [map(list, “a”), map(list, “b”), map(list, “c”)]

Slide 50

Slide 50 text

分解して見てみよう list(map( list, list(map( map, map(lambda map:list, map:='map'), map )))) [list, list,...] を返す無名関数 def func(x): return list map(func, ‘abc’) # [list,list,list] ここは上の行の map:=”map”が評価された後なので mapという変数に入った“map”という文字列 標準関数mapを上書き🤪

Slide 51

Slide 51 text

分解して見てみよう list(map( list, list(map( map, map(lambda map:list, map:='map'), map )))) 内側だけ簡略化すると x = map(map, [list, list, list], “map”) print([list(y) for y in x]) # [[['m']], [['a']], [['p']]] 簡略化verのfor文がダサいので書き換えたい

Slide 52

Slide 52 text

分解して見てみよう list(map(list, list(map(map, [list, list, list], “map”)))) 外側は非常にシンプル 要素1つ1つにfor文を回してlist化したいだけ map(map, [list, list, list], “map”) listの全ての要素にlistを実行

Slide 53

Slide 53 text

正解は ② [[['m']], [['a']], [['p']]] list(map(list,list(map(map,map(lambda map:list,map:='map'),map))))

Slide 54

Slide 54 text

54 *M,M=[*"123"];"M"+M 以下のPythonスクリプトの実行結果は? ① 6 ② “M3” ③ “M*MMM*MM” ④ -1

Slide 55

Slide 55 text

正解は ② ”M3” *M,M=[*"123"];"M"+M 🎉

Slide 56

Slide 56 text

分解して見てみよう *M,M=[*"123"];"M"+M インタプリタ上での ;(セミコロン) は改行扱い

Slide 57

Slide 57 text

分解して見てみよう *M,M=[*"123"] "M"+M “M” + 何か であることは明確だった🤪

Slide 58

Slide 58 text

Pythonにおけるunpack # listによるunpack [*“123”] # [“1”, “2”, “3‘] [*[1,2,3], *[4,5,6]] # [1,2,3,4,5,6] # unpack代入 *a, b, c = [1, 2, 3, 4, 5] print(a) # [1, 2, 3] print(b) # [4] print(c) # [5] **argsなど可変長引数などが応用先 ポインタの考え方が分かっていると飲み込みやすい

Slide 59

Slide 59 text

分解して見てみよう *M,M=[*"123"] "M"+M 文字列に対するunpack [“1”, “2”, “3”] 1つを除いた前半全てを *Mが受け取る 前から実行され、変数Mには最後の数値が入る

Slide 60

Slide 60 text

正解は ② ”M3” *M,M=[*"123"] "M"+M

Slide 61

Slide 61 text

お疲れ様でした!😁

Slide 62

Slide 62 text

ワシらの難読クイズは108式まであるぞ(*) * どうやら各言語合わせると社内ストックは本当に100以上あるみたいです🤪

Slide 63

Slide 63 text

63 @m3_engineering で待っています リモート可/時給2500円/PC貸与/内容は個人フルカスタム GAFAやメガベンチャー出身者にも囲まれる少数精鋭組織で 医療業界最大規模の自社プロダクトに触れられる 学業優先で通年募集なインターン情報もたまに流れます