python - इस पायथन स्ट्रिंग का आकार एक असफल अंतर रूपांतरण पर क्यों बदलता है



string python-3.x (1)

ट्वीट से यहां :

import sys
x = 'ñ'
print(sys.getsizeof(x))
int(x) #throws an error
print(sys.getsizeof(x))

हमें 74, फिर 77 बाइट्स के लिए दो getsizeof कॉल getsizeof हैं।

ऐसा लगता है कि हम असफल इंट कॉल से ऑब्जेक्ट में 3 बाइट जोड़ रहे हैं।

ट्विटर से कुछ और उदाहरण (आपको फिर से आकार को 74 पर रीसेट करने के लिए अजगर को फिर से शुरू करने की आवश्यकता हो सकती है):

x = 'ñ'
y = 'ñ'
int(x)
print(sys.getsizeof(y))

77!

print(sys.getsizeof('ñ'))
int('ñ')
print(sys.getsizeof('ñ'))

74, फिर 77।


वह कोड जो CPython 3.6 में स्ट्रिंग्स को इनटार्स में परिवर्तित करता है, इसके साथ काम करने के लिए स्ट्रिंग के UTF-8 फॉर्म का अनुरोध करता है :

buffer = PyUnicode_AsUTF8AndSize(asciidig, &buflen);

और स्ट्रिंग UTF-8 का प्रतिनिधित्व करता है पहली बार यह अनुरोध किया गया है और इसे स्ट्रिंग ऑब्जेक्ट पर कैश करता है :

if (PyUnicode_UTF8(unicode) == NULL) {
    assert(!PyUnicode_IS_COMPACT_ASCII(unicode));
    bytes = _PyUnicode_AsUTF8String(unicode, NULL);
    if (bytes == NULL)
        return NULL;
    _PyUnicode_UTF8(unicode) = PyObject_MALLOC(PyBytes_GET_SIZE(bytes) + 1);
    if (_PyUnicode_UTF8(unicode) == NULL) {
        PyErr_NoMemory();
        Py_DECREF(bytes);
        return NULL;
    }
    _PyUnicode_UTF8_LENGTH(unicode) = PyBytes_GET_SIZE(bytes);
    memcpy(_PyUnicode_UTF8(unicode),
              PyBytes_AS_STRING(bytes),
              _PyUnicode_UTF8_LENGTH(unicode) + 1);
    Py_DECREF(bytes);
}

अतिरिक्त 3 बाइट्स UTF-8 प्रतिनिधित्व के लिए हैं।

आप सोच रहे होंगे कि जब स्ट्रिंग or '40' या 'plain ascii text' तरह आकार में क्यों नहीं बदलती है। ऐसा इसलिए है क्योंकि यदि स्ट्रिंग "कॉम्पैक्ट एससीआई" प्रतिनिधित्व में है , तो पायथन एक अलग यूटीएफ -8 प्रतिनिधित्व नहीं बनाता है। यह ASCII प्रतिनिधित्व को सीधे लौटाता है , जो पहले से ही मान्य UTF-8 है:

#define PyUnicode_UTF8(op)                              \
    (assert(_PyUnicode_CHECK(op)),                      \
     assert(PyUnicode_IS_READY(op)),                    \
     PyUnicode_IS_COMPACT_ASCII(op) ?                   \
         ((char*)((PyASCIIObject*)(op) + 1)) :          \
         _PyUnicode_UTF8(op))

आपको यह भी आश्चर्य हो सकता है कि आकार '1' might '1' जैसी किसी चीज़ के लिए क्यों नहीं बदलता है। वह U + FF11 FULLWIDTH DIGIT ONE है, जो int को '1' बराबर मानता है। ऐसा इसलिए है क्योंकि स्ट्रिंग-टू-इंट प्रक्रिया में पहले के चरणों में से एक है

asciidig = _PyUnicode_TransformDecimalAndSpaceToASCII(u);

जो सभी व्हाट्सएप वर्णों को ' ' परिवर्तित करता है और सभी यूनिकोड दशमलव अंकों को संबंधित ASCII अंकों में परिवर्तित करता है। यह रूपांतरण मूल स्ट्रिंग को लौटाता है यदि यह कुछ भी बदलना समाप्त नहीं करता है, लेकिन जब यह परिवर्तन करता है, तो यह एक नया स्ट्रिंग बनाता है, और नया स्ट्रिंग वह है जिसे UTF-8 प्रतिनिधित्व प्राप्त होता है।

उन मामलों के लिए जहां एक स्ट्रिंग पर int कॉल करना ऐसा लगता है कि यह दूसरे को प्रभावित करता है, वे वास्तव में समान स्ट्रिंग ऑब्जेक्ट हैं। ऐसी कई स्थितियां हैं जिनके तहत पायथन स्ट्रिंग्स का पुन: उपयोग करेगा, सभी दृढ़ता से विस्तार कार्यान्वयन भूमि में, जैसा कि हमने अब तक चर्चा की है। 'ñ' , पुन: उपयोग होता है क्योंकि यह लैटिन -1 रेंज ( '\x00' - '\xff' ) में एकल-वर्ण स्ट्रिंग है, और कार्यान्वयन भंडार और पुन: उपयोग करता है





python-internals