2012-10-31 10 views
5

एक अजगर विच्छेदन में, मैंने आईपी स्ट्रिंग को कार्यात्मक प्रोगोगिंग तरीके में एक पूर्णांक में परिवर्तित करने के लिए एक फ़ंक्शन देखा। यहां the Link है।आईपी स्ट्रिंग को एक पूर्णांक में परिवर्तित करने के लिए कार्यात्मक प्रोग्रामिंग कोड को कैसे समझें?

फ़ंक्शन को एक पंक्ति में लागू किया गया है।

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

हालांकि, मेरे पास funcional प्रोग्रामिंग के कुछ विचार हैं। क्या कोई भी कार्य को विस्तार से समझा सकता है? मुझे "नक्शा" और "कम करने" का कुछ ज्ञान है। लेकिन मैं नहीं जानता कि "|" और "खंड" का मतलब यहां है।

धन्यवाद।

+0

एक पक्ष नोट के रूप में में यह व्यक्त की तरह एक सा कह सकते हैं, अजगर बैटरी के इस प्रकार भी शामिल है 0] ' – georg

+0

मुझे आश्चर्य है कि प्रदर्शन अंतर क्या है? – Keith

उत्तर

13

sum और chunklambda समारोह reduce के लिए पारित करने के लिए तर्क हैं। | बाइनरी या ऑपरेटर है।

बात इस तरह काम करता है:

  • ip.split(".") स्ट्रिंग की एक सूची देता है, प्रत्येक बिंदीदार तार का एक टुकड़ा ("192.168.0.1" =>["192", "168", "0", "1"] करने के लिए इसी;

  • map अपनी पहली संकार्य पर लागू होता है इसके दूसरे ऑपरेंड के प्रत्येक तत्व (["192", "168", "0", "1"] =>[192, 168, 0, 1]);

  • reduce सूची से पहले दो तर्क लेता है और lambda पर लागू होता है; तो यह फिर से lambda और सूची के अगले तत्व के परिणाम के साथ करता है; और इसी तरह।

  • labmda फ़ंक्शन (स्पॉट पर परिभाषित एक अज्ञात फ़ंक्शन) यह करता है: पहला तर्क लेता है, इसे आठ बिट्स और ओआरएस द्वारा नए हिस्से में बदल देता है; इस प्रकार, क्या होता है कि परिणाम की तरह की जाती है है:

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

    जो वास्तव में है क्या "बिंदीदार फार्म" का प्रतिनिधित्व करता है (यह एक 32 बिट अहस्ताक्षरित पूर्णांक है, जो एक आईपी आईपीवी 4 में है इंगित करने के लिए सिर्फ एक आशुलिपि है ('! मैं, socket.inet_aton (आईपी) `struct.unpack) [: - आप इसे आधार 256)

+0

बहुत बहुत धन्यवाद। मैंने कोड समझा है। मुझे आश्चर्य है कि एक इंटीजर से आईपी स्ट्रिंग को इस तरह से परिवर्तित करने के लिए फ़ंक्शन को कैसे कार्यान्वित किया जाए? – zfz

5

| एक bitwise, logical or है:

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

कम कॉल वर्तमान कुल चल रहा है और map() फ़ंक्शन के परिणाम के अगले (पूर्णांक) मूल्य के साथ lambda। इसलिए, यह क्या कर रहा है एक पाश में निम्नलिखित:

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

जहां map(int, ip.split(".")) पूर्णांक के अनुक्रम में रखता आईपी पते बदल गया; 1.2.3.4[1, 2, 3, 4] बन जाता है।

<< एक bitwise left shift, इस मामले में है 8 बिट द्वारा:

>>> 1 << 8 
256 

तो, एक आईपी पता से प्रत्येक पूर्णांक भाग के लिए, यह 8 पदों द्वारा छोड़ गए मूल्य बदलाव, और बिट्स कहते हैं पते के अगले भाग के उस नंबर पर।

यह सही समझ में आता है, क्योंकि आईपी पता 32-बिट संख्या के अलावा कुछ भी नहीं है, और स्ट्रिंग नोटेशन उस संख्या को 8 बिट्स के 4 हिस्सों में विभाजित करता है, और 'प्रिंट्स' उन 8 बिट्स में से प्रत्येक का पूर्णांक मान के बीच में . चरित्र के साथ।

यह एक द्विआधारी संख्या के रूप में प्रत्येक चरण मुद्रित करने के लिए मदद करता है:

>>> 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'