Upgrade to Pro — share decks privately, control downloads, hide ads and more …

エムスリー流!難読クイズを作ってPythonの深淵に触れるコツ! - 技育CAMPアカデミア

エムスリー流!難読クイズを作ってPythonの深淵に触れるコツ! - 技育CAMPアカデミア

以下イベントで学生向けに発表した内容です

エムスリー流!難読クイズを作ってPythonの深淵に触れるコツ! / 技育CAMPアカデミア
https://talent.supporterz.jp/events/48051ff8-6282-4f41-becd-825d7781a994/

vaaaaanquish

October 30, 2024
Tweet

More Decks by vaaaaanquish

Other Decks in Technology

Transcript

  1. 数値には接頭辞を付ける事ができる print( 1000 ) # 10進数 print( 0b10 ) #

    2進数 binary print( 0o10 ) # 8進数 octal print( 0x10 ) # 16進数 hexadecimal print( 0000 ) # 0 print( 0001 ) # SyntaxError 前のアンダースコアも合わせて こういった数値の記法は整数リテラル(integer literal)と呼ばれる機能の1つ 多くの言語で実装されている
  2. 算術/ビット演算子を振り返り print( 1 - 1 ) # 0 print( 1

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

    ~ 0 ^ -0 0 - 0 - ~ 0 0 - 0 - -1 1 AND、XORが優先的に処理される ast.parseしてみよう!
  4. 申し遅れました 河合(@vaaaaanquish) エムスリー株式会社 VPoE PIVOT株式会社 技術顧問 高専 → 大学 →

    Sansan/Yahoo!/CADDi → M3 Google Cloud Champion Innovator (AI/ML) MLコンテスト入賞、書籍執筆、podcast devsumi、Google Cloud Next等で登壇
  5. 超少数精鋭エンジニア 100人体制! あらゆる技術の知識を活かし イノベーションを創出する ギークの登竜門 ISUCON 2023入賞 日本IT団体連盟 CYBER INDEX認定

    GoodDesign賞受賞 技術書典 最新刊完売 国際ジャーナル1st 書籍執筆経験者多数 テックブログ年100記事以上 社内LT250回、輪読会、開発合宿 300 Star超えのOSS
  6. 伝統的なギークカルチャー 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
  7. Assignment Expressions # 評価のタイミングで代入を行える演算子 print(x:=1) # 1 <- 評価結果は代入値になる print(x)

    # 1 他言語ではセイウチ演算子(walrus operator)と呼ばれる PEP 572を見ると「walrus operatorじゃないんでよろしく」的な文言が
  8. 分解して見てみよう if (c := ('ω')<"hi") : (d >_< b) else:

    (c^0^c)-~3 変数cに値を代入している (“ω”) と “hi” を比較した結果
  9. Pythonのtuple print( (1, 2) ) # (1, 2) print( (1)

    ) # 1 print( (1, ) ) # (1, ) print( (((((1))))) ) # 1 括弧の末尾に , (カンマ) がある/ない で 評価結果が変わる
  10. 分解して見てみよう if (c := 'ω' < "hi") : (d >_<

    b) else: (c^0^c)-~3 (“ω”)は実質 ”ω” 文字列同士の比較は Unicodeコードポイントの比較 アルファベットがUnicode上で 前の方にある事を知っていると ここは False とわかる
  11. ビット演算子を振り返り print( 1 - 1 ) # 0 print( 1

    & 0 ) # 0 AND演算子 print( ~0 ) # -1 NOT演算子 => -(x+1) print( 0 ^ 1 ) # 1 XOR演算子 ビット演算子は難読化では必修 特にNOTは実質的に -(x+1) として扱えるので難読化で便利
  12. 分解して見てみよう if (c:=('ω')<"hi") : (d >_< b) else: 0 -

    -4 0^0^0は当然0 ~3は-(x+1)に当てはめて-4 この算術の結果は 4
  13. ちなみに… if True : (d >_< b) else: (c^0^c)-~3 Traceback

    (most recent call last): File "<string>", line 1, in <module> NameError: name 'd' is not defined ここは評価時Errorなので構文として 成り立っていれば何でも良い場所! (d >_< b) if (c:=('ω')<"hi") else (c^0^c)-~3 を前から読もうとすると誤爆する🤪
  14. 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として使われる
  15. Pythonのmap # mapはiterableなオブジェクト全てに関数を適応します # 返り値はIteratorなのでlist function等を適応する必要があります map(str, [1, 2, 3])

    # <map object at ...> 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”)]
  16. 分解して見てみよう 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を上書き🤪
  17. 分解して見てみよう 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文がダサいので書き換えたい
  18. 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など可変長引数などが応用先 ポインタの考え方が分かっていると飲み込みやすい