Intel Twitter Twitterイメージの解決

信じられないほどのアンダースコア、ラムダ、非常にまれな__import__関数を含むホラーストーリーがあります。







どのような獣と彼は何をしていますか?



もちろん、普通の人として、インタープリターでコードを再入力し、何が起こるかを見ることができます。 しかし、真夜中を過ぎてからの時間なので、あなたの手で理解することはより興味深いです。



それでもコードを書き換える必要があります。 あなたが起動する誘惑に屈することを恐れているなら-紙にもっと書いてください。



したがって、まず最初に、このすべてを表示するようにしましょう。傾斜をつけずに、同時に(できるだけ)テキストを読みやすくするようにします。



getattr( __import__(True.__class__.__name__[1] + [].__class__.__name__[2]), ().__class__.__eq__.__class__.__name__[:2] + ().__iter__().__class__.__name__[5:8] ) ( 1, ( lambda _, __: _(_, __) )( lambda _, __: chr(__ % 256) + _(_, __ // 256) if __ else "", 882504235958091178581291885595786461602115 ) )
      
      





私たちはPEP8からはほど遠いので、そのようなレビューをコードに送信することはまだ価値がありませんが、すでにはるかに優れています。



getattrがあるので、最初の括弧は関数を「返す」ものであり、2番目は引数のリストです。

Getattrは、最初の引数としてオブジェクトを取り、2番目の引数として目的の属性を取ります。 オブジェクトから始めましょう。



実際、__ import__関数はおなじみの「XからYをZとしてインポート」が変換するものです。 この機能は非常にまれであり、「戦闘」状況での使用は隅々に見られるわけではありません。 ドキュメントでその構造をより詳しく理解できますが、この場合、この関数は式に似ていることを宣言します。



 from True.__class__.__name__[1] + [].__class__.__name__[2] import ().__class__.__eq__.__class__.__name__[:2] + ().__iter__().__class__.__name__[5:8])
      
      





最初の部分は単純です-手順を進めます。 TrueとFalseのニーズのために、pythonには特別なタイプの「bool」があり、これはまさに__class __.__ name__チェーンが返すものです。 最初の要素を取ります、それは文字「o」になります。

2番目の文字の検索はそれほど複雑ではありません-[]はリスト、リストは「リスト」、「リスト」[2]は「s」です。

ミニパズルの最初の部分は正常に解決されました。



 from os import ().__class__.__eq__.__class__.__name__[:2] + ().__iter__().__class__.__name__[5:8])
      
      





2番目の部分を扱います。 「()」はタプル、つまり タプル、__ eq__は、比較演算子「==」の「魔法の」ラッパーです。 ここで、「== .__ class__」が何らかの「関数」であると考える場合、まず既知の実体に踏み込みます。 これは実際には「wrapper_descriptor」であり、別のケースでは誰も気付かないでしょうが、ここでは非常に重要です。 残念ながら、私は組み込みの魔法のメソッドのクラスの命名の秘密に専念していないので、コメントでの開示を期待しています。 「wrapper_descriptor」[:2]スライスを取り、「wr」を取得します。



osモジュールにはwrで始まるメソッドが1つしかなく、これは明らかに記述されているため、これ以上理解する必要はありません。

この単語の2番目の部分の分析は自分で行うことができ、複雑なことは何もありません。



 from os import write
      
      





前に見つけたように、今度はあまり明確でない引数でwrite関数を呼び出さなければなりません。



 from os import write write(1, ( lambda _, __: _(_, __) ) ( lambda _, __: chr(__ % 256) + _(_, __ // 256) if __ else "", 882504235958091178581291885595786461602115 ) )
      
      





最初の引数は、書き込み先のハンドルでなければなりません。 私たちの場合、これは1で、これは...標準出力です! 簡単に言えば、os.writeは印刷として機能します。



その後、次のことが起こります。最初の匿名関数は角括弧で囲まれます。つまり、ここで呼び出されます。



彼女が何をしているのかをよりよく理解するために、内容について少し考えた後、通常の方法として書き留めます。



 lambda _, __: _(_, __)
      
      





2つの引数を受け入れ、最初のメソッド__call__が呼び出されます。 最初の引数が関数であると仮定するのは論理的で、それから:



 def function_one(inner, argument): return inner(inner, argument)
      
      





最初のパラメーターによって渡された関数への引数を「転送」する以外は何も起こりません。 この機能は何ですか?



 lambda _, __: chr(__ % 256) + _(_, __ // 256) if __ else "",
      
      





chrメソッドが表示されるため、数字を文字に変換します。 人間が書き直します:



 def function_two(inner, ordC): if ordC: return chr(ordC % 256) + inner(inner, ordC // 256) else: return ""
      
      





これを注意深く見て、次のことが起こることに気付きます:数値を取得し、それを剰余で256で除算し、除算の剰余をシンボルとして格納し、数値が256未満になるまで商をさらに再帰的に転送します(つまり、数値// 256 == 0)。 それほどトリッキーではありません。



送信する膨大な数は上記に記録されています。 私たちはそれを理解したので、すべてをまとめて人間のpythonでそのようなものを書いてみましょう。



 from os import write def recursive_print(number): if number: write(1, chr(number % 256)) recursive_print(number // 256) else: return recursive_print(882504235958091178581291885595786461602115)
      
      





ロシアでは母の日に別の日が割り当てられていますが、このアドバイスはまだ従う価値があります。



All Articles