2012-04-10 13 views
9

कॉपी न करें यदि आप पाइथन स्ट्रिंग पर string.split() का उपयोग करते हैं, तो यह तारों की एक सूची देता है। ये सबस्ट्रिंग जो विभाजित हो चुके हैं वे पैरेंट स्ट्रिंग के अपने हिस्से की प्रतियां हैं।संदर्भ द्वारा अपरिवर्तनीय तारों के स्लाइस और

क्या इसके बजाय कुछ सस्ता स्लाइस ऑब्जेक्ट प्राप्त करना संभव है जिसमें केवल एक संदर्भ, ऑफसेट और बिट्स को विभाजित करने के लिए लंबाई हो?

और क्या इन उप-तारों को निकालने और उनका इलाज करने के लिए कुछ 'स्ट्रिंग व्यू' होना संभव है जैसे कि वे अपने बाइट्स की एक प्रति बनाये बिना तार हैं?

(जैसा कि मैंने बहुत बड़ी तार है मैं पूछता हूँ मैं काट करना चाहते हैं और कभी-कभी स्मृति से बाहर चल रहा हूँ;। प्रतियां को हटाने के एक सस्ते प्रोफ़ाइल निर्देशित जीत होगा)

+0

बफर() का उपयोग करने वाले नीचे दिए गए उत्तर केवल 2.7 पर लागू होते हैं। मेमोरीव्यू() को यूनिकोड तारों के साथ उपयोग नहीं किया जा सकता है, जो 3.x में सामान्य स्ट्रिंग हैं। –

उत्तर

17

buffer आप रीड-ओनली दे देंगे एक स्ट्रिंग पर देखें।

>>> s = 'abcdefghijklmnopqrstuvwxyz' 
>>> b = buffer(s, 2, 10) 
>>> b 
<read-only buffer for 0x7f935ee75d70, size 10, offset 2 at 0x7f935ee5a8f0> 
>>> b[:] 
'cdefghijkl' 
+0

वाह, और यहां मैं सोच रहा था कि मैं सभी बिल्टिन जानता था। टीआईएल। –

+0

इस पर विस्तार, क्या इन बफर में विभाजित() टिंग के लिए मानक व्यंजन/मॉड्यूल हैं? – Will

+0

नहीं, लेकिन आप शायद इनमें से एक [http://stackoverflow.com/questions/3862010/is-there-a-generator-version-of-string-split-in-python) को अनुकूलित कर सकते हैं। –

1

यहां त्वरित स्ट्रिंग-जैसे बफर रैपर है जिसके साथ आया था; मैं स्ट्रिंग का उपभोग करने के लिए अपेक्षित कोड को बदलने के बिना क्लासिक तारों के स्थान पर इसका उपयोग करने में सक्षम था।

class StringView: 
    def __init__(self,s,start=0,size=sys.maxint): 
     self.s, self.start, self.stop = s, start, min(start+size,len(s)) 
     self.size = self.stop - self.start 
     self._buf = buffer(s,start,self.size) 
    def find(self,sub,start=0,stop=None): 
     assert start >= 0, start 
     assert (stop is None) or (stop <= self.size), stop 
     ofs = self.s.find(sub,self.start+start,self.stop if (stop is None) else (self.start+stop)) 
     if ofs != -1: ofs -= self.start 
     return ofs 
    def split(self,sep=None,maxsplit=sys.maxint): 
     assert maxsplit > 0, maxsplit 
     ret = [] 
     if sep is None: #whitespace logic 
      pos = [self.start,self.start] # start and stop 
      def eat(whitespace=False): 
       while (pos[1] < self.stop) and (whitespace == (ord(self.s[pos[1]])<=32)): 
        pos[1] += 1 
      def eat_whitespace(): 
       eat(True) 
       pos[0] = pos[1] 
      eat_whitespace() 
      while pos[1] < self.stop: 
       eat() 
       ret.append(self.__class__(self.s,pos[0],pos[1]-pos[0])) 
       eat_whitespace() 
       if len(ret) == maxsplit: 
        ret.append(self.__class__(self.s,pos[1])) 
        break 
     else: 
      start = stop = 0 
      while len(ret) < maxsplit: 
       stop = self.find(sep,start) 
       if -1 == stop: 
        break 
       ret.append(self.__class__(self.s,self.start+start,stop-start)) 
       start = stop + len(sep) 
      ret.append(self.__class__(self.s,self.start+start,self.size-start)) 
     return ret 
    def split_str(self,sep=None,maxsplit=sys.maxint): 
     "if you really want strings and not views" 
     return [str(sub) for sub in self.split(sep,maxsplit)] 
    def __cmp__(self,s): 
     if isinstance(s,self.__class__): 
      return cmp(self._buf,s._buf) 
     assert isinstance(s,str), type(s) 
     return cmp(self._buf,s) 
    def __len__(self): 
     return self.size 
    def __str__(self): 
     return str(self._buf) 
    def __repr__(self): 
     return "'%s'"%self._buf 

if __name__=="__main__": 
    test_str = " this: is: a: te:st str:ing :" 
    test = Envelope.StringView(test_str) 
    print "find('is')" 
    print "\t",test_str.find("is") 
    print "\t",test.find("is") 
    print "find('is',4):" 
    print "\t",test_str.find("is",4) 
    print "\t",test.find("is",4) 
    print "find('is',4,7):" 
    print "\t",test_str.find("is",4,7) 
    print "\t",test.find("is",4,7) 
    print "split():" 
    print "\t",test_str.split() 
    print "\t",test.split() 
    print "split(None,2):" 
    print "\t",test_str.split(None,2) 
    print "\t",test.split(None,2) 
    print "split(':'):" 
    print "\t",test_str.split(":") 
    print "\t",test.split(":") 
    print "split('x'):" 
    print "\t",test_str.split("x") 
    print "\t",test.split("x") 
    print "''.split('x'):" 
    print "\t","".split("x") 
    print "\t",Envelope.StringView("").split("x") 
+0

आपको असली चीज को वास्तविक चीज़ में एक सिद्धांत के रूप में लिखने पर विचार करना चाहिए। –

+0

32-बिट सिस्टम पर, इस वर्ग का हर एक उदाहरण 642 बिट सिस्टम पर 232 बाइट मेमोरी का उपयोग करेगा, यह और भी अधिक होगा, इसलिए यह केवल लंबे सबस्ट्रिंग के लिए ही लायक होगा। स्मृति को कम करने के लिए आपको कम से कम आधा राशि का उपभोग करने के लिए कम से कम '__slots__' का उपयोग करना चाहिए। –

+0

और भी स्मृति को सहेजने के लिए, या तो बफर ऑब्जेक्ट से छुटकारा पाएं, या 'एस', 'स्टार्ट' और 'स्टॉप' से छुटकारा पाएं। किसी भी मामले में, 'आकार' से छुटकारा पाएं। –

1

स्ट्रिंग ऑब्जेक्ट्स हमेशा पायथन में एक एनयूएल-समाप्त बफर को इंगित करते हैं, इसलिए सबस्ट्रिंग की प्रतिलिपि बनाई जानी चाहिए। जैसा कि इग्नासिओ ने इंगित किया है, आप स्ट्रिंग मेमोरी पर केवल पढ़ने के लिए दृश्य प्राप्त करने के लिए buffer() का उपयोग कर सकते हैं। buffer() बिल्ट-इन फ़ंक्शन को अधिक बहुमुखी memoryview ऑब्जेक्ट्स द्वारा अधिलेखित किया गया है, हालांकि, जो पाइथन 2.7 और 3.x (buffer() में पाइथन 3.x में उपलब्ध है) में उपलब्ध हैं।

s = "abcd" * 50 
view = memoryview(s) 
subview = view[10:20] 
print subview.tobytes() 

इस कोड को प्रिंट

cdabcdabcd 

जैसे ही आप tobytes() फोन, स्ट्रिंग की एक प्रतिलिपि बनाया जाएगा, लेकिन एक ही होता है जब इग्नेसियो के जवाब में ही पुराना buffer वस्तुओं टुकड़ा करने की क्रिया।

+0

हां, इसकी प्रतिलिपि मैं बचने के लिए बहुत उत्सुक हूं; कुछ ऐसा कैसे प्राप्त होता है, इस पर विचार हमेशा एक दृश्य बना रहता है फिर भी एक स्ट्रिंग की तरह काम करता है? – Will

+0

@ विल: इग्नासिओ का समाधान और यह दोनों, प्रतिलिपि से बचें यदि आप केवल बफर/मेमोरीव्यू के आसपास रहते हैं। यदि आप इसे स्ट्रिंग के रूप में उपयोग करना चाहते हैं, तो आपको अस्थायी रूप से इसे एक स्ट्रिंग में बदलना होगा और उस पर काम करना होगा।और जैसा कि मैंने पहले कहा था, पायथन स्ट्रिंग बफर एनयूएल-टर्मिनेटेड हैं, इसलिए स्ट्रिंग बफर के रूप में किसी अन्य स्ट्रिंग के केवल एक हिस्से का उपयोग करना असंभव है। –

+0

मेरा मतलब था बतख की तरह अधिक quacking; मैंने अपने स्ट्रिंग व्यू में 'इन' और पुनरावृत्ति को जोड़ा है और यह अच्छी तरह से काम कर रहा है। बस शर्मिंदा है कि यह वास्तव में अंतर्निहित नहीं है। – Will

संबंधित मुद्दे