2019-01-01に更新

あけおめからPython

皆さんへのメッセージです。

謹賀, 新年=(lambda x:(not x,x))([])
新年.append((謹賀+謹賀)**((謹賀+謹賀)**(謹賀+謹賀+謹賀))-(謹賀+謹賀+謹賀)**(謹賀+謹賀+謹賀)-(謹賀+謹賀))
新年.append((謹賀+謹賀)**((謹賀+謹賀)**(謹賀+謹賀+謹賀)-謹賀)+謹賀)
新年.append(新年[-謹賀]+謹賀)
新年.append(新年[謹賀-謹賀])
新年.append(新年[謹賀])
新年.append(新年[謹賀+謹賀]+((謹賀+謹賀)*(謹賀+謹賀))**(謹賀+謹賀)-謹賀)
新年.append(新年[謹賀-謹賀])
新年.append(新年[謹賀])
新年.append(新年[謹賀+謹賀]+(謹賀+謹賀)**(謹賀+謹賀+謹賀))
新年.append(新年[謹賀-謹賀])
新年.append(新年[謹賀+謹賀])
新年.append(新年[謹賀])
print(bytes(新年).decode('utf-8'))

実行してみましょう。

小ネタは置いといて。

この前、ふとリスト内包表記の中身(ローカル変数空間)が気になったので以下のコードを実行してみました。

[i for i in [0] if print(locals()) or 1]

結果はこうなりました。

{'i': 0, '.0': <tuple_iterator object at 0x0000018E8BDDE518>}

はい、コードの実行フレームが分かれていますね。ところで表示された辞書オブジェクトのキー'.0'って何でしょう?気になったので以下のコードを実行してみました。もし、私の予想が正しければ実行は終了しないはずです。

[i for i in [0] if locals().__setitem__('.0', range(2).__iter__()) or 1]

実際にやってみた結果、[0]が出力されました。どういうことなんでしょう…?
__setitem__をした後にprint(locals())で中身を調べてみます。

[i for i in [0] if locals().__setitem__('.0', range(2).__iter__()) or print(locals()) or 1]

結果はこのようになりました。

{'i': 0, '.0': <tuple_iterator object at 0x0000018E8BDDE518>}

要素を変えることができていません。なぜでしょう? 残念なことにいくつか仮説を立ててみたのですが、そのどれもが間違っていました。

仮説1. ローカル変数空間はループごとに新しく作られている

これは簡単に確かめることができます。

[i for i in [0,1] if print(id(locals())) or 1]

これで表示される数が2つとも等しければ使いまわされていることが証明できます。私が実行した結果はこうなりました。

1711743637328
1711743637328
[0, 1]

はい、一致していますね。異なるオブジェクトのIDが一致することはまずありえませんので、ローカル変数空間は使いまわされていることがわかりました。

仮説 2. '.0'というキーは例外的に書き換えできない

当然なんてことはありませんでした。

>>> x = {}
>>> x['.0'] = 12
>>> x
{'.0': 12}
>>> x['.0'] = 4
>>> x
{'.0': 4}

仮説 3. ローカル名前空間のオブジェクトがdictではない

だんだん投げやりになってきましたね。当然そんなわけなく、dictでした…。

>>> [i for i in [0] if print(type(locals())) or 1]
<class 'dict'>
[0]

とまぁ、こんな感じでPythonサイドからの解明は終ぞできませんでした…。今年はPythonのコードリーディングをしようかと考えています。

リスト内包表記は単体でチューリング完全と聞いたので

リスト内包表記だけでいくつか書いてみました。まずは普通にFizzBuzzから。

# FizzBuzz in list comprehension
[('Fizz' if not i%3 else '')+('Buzz' if not i%5 else '')+(str(i) if i%3 and i%5 else '') for i in range(20)]

続いてはAtCoder Beginners SelectionよりCard Game for Twoを解くプログラム。結構強引ですね。

print(sum(x-y for x, y in zip(*(lambda x:((x.append(0) if len(x)%2 else None),x.sort(reverse=True),(x[::2],x[1::2]))[2])((input(), [int(i) for i in input().split()])[1]))))

正直言うと、自分も難読化以上の意味はないと思いました…。

ですが、いろいろやっているとやはり内包表記のポテンシャルは高いと感じました。あなたもやってみてはいかが?

for文で遊ぶ

for i in range(20):
    print(i)

と同じプログラムをrange関数なしで黒魔術っぽくやってみたいと思います。

for i in (lambda x: (x, x.append(x))[0])([]):
    print(len(i)-1)
    i.append(i)
    if i[20:]:
        i.clear()

循環参照をうまく使ってみました。難読化以上の意味はないです

私からは以上です。皆さん、今年も元気に行きましょう!


frodo821

Crieitはβバージョンで開発中です。進捗は公式Twitterアカウントをフォローして確認してください。 興味がある方は是非記事の投稿もお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

関連記事

コメント