5

Pythonの議論の中で、関数プログラミングの方法でIP文字列を整数に変換する関数を見ました。これがリンクです。

関数は1行で実装されます。

def ipnumber(ip):
    return reduce(lambda sum, chunk: sum <<8 | chunk, map(int, ip.split(".")))

しかし、私には機能プログラミングのアイデアがほとんどありません。誰かが機能を詳しく説明してもらえますか?「map」と「reduce」についてある程度の知識があります。しかし、私は「|」が何であるかわかりません 「チャンク」はここで意味します。

ありがとう。

4

2 に答える 2

13

sumおよびは、に渡される関数chunkの引数です。はバイナリまたは演算子です。lambdareduce|

物事は次のように機能します:

  • ip.split(".")文字列のリストを返します。各文字列は点線の文字列の一部に対応しています("192.168.0.1"=> ["192", "168", "0", "1"];

  • map最初のオペランドを2番目のオペランドの各要素に適用します(["192", "168", "0", "1"]=> [192, 168, 0, 1]);

  • reduceリストから最初の2つの引数を取り、それらに適用lambdaします。次に、ラムダとリストの次の要素の結果を使用してこれを再度実行します。等々。

  • 関数(そのlabmda場で定義された無名関数)はこれを行います。最初の引数を取り、それを8ビットシフトし、新しいチャンクにORします。したがって、結果は次のように計算されます。

    (((192<<8 | 168) << 8 | 0)<<8 | 1) = 192<<24 | 168<<16 | 0<<8 | 1
    

    これはまさに「点線の形式」が表すものです(32ビットの符号なし整数を示すための省略形です。これはIPv4のIPです。256をベースに表現するのと少し似ていると言えます)。

于 2012-10-31T10:58:58.023 に答える
5

|ビット単位、論理、または:

>>> 0 | 1
1
>>> 1 | 1
1

Reduceはlambda、関数の出力の現在の現在の合計と次の(整数)値を使用して呼び出しを減らしますmap()。したがって、ループ内で次のことを実行しています。

sum = 0
for chunk in map(int, ip.split(".")):
    sum = (sum << 8) | chunk

ここでmap(int, ip.split("."))、IPアドレスを整数のシーケンスに変換しました。1.2.3.4になり[1, 2, 3, 4]ます。

これ<<ビット単位の左シフトであり、この場合は8ビットです。

>>> 1 << 8
256

したがって、IPアドレスの整数部分ごとに、値を8桁左にシフトし、アドレスの次の部分のビットをその数値に追加します。

IPアドレスは32ビットの数値に過ぎず、文字列表記はその数値を8ビットの4つのチャンクに分割し、それらの8ビットのそれぞれの整数値を.文字で「出力」するため、これは完全に理にかなっています。の間に。

各ステージを2進数として印刷すると便利です。

>>> map(int, '1.2.3.4'.split('.'))
[1, 2, 3, 4]
>>> bin(1)
'0b1'
>>> bin(2)
'0b10'
>>> bin(3)
'0b11'
>>> bin(4)
'0b100'
>>> bin(1 << 8)
'0b100000000'
>>> bin(1 << 8 | 2)
'0b100000010'
>>> bin((1 << 8 | 2) << 8)
'0b10000001000000000'
>>> bin((1 << 8 | 2) << 8 | 3)
'0b10000001000000011'
>>> bin(((1 << 8 | 2) << 8 | 3) << 8)
'0b1000000100000001100000000'
>>> bin(((1 << 8 | 2) << 8 | 3) << 8 | 4)
'0b1000000100000001100000100'
于 2012-10-31T10:55:10.600 に答える