টি এল; ডিআর
পাইথন 2 এর জন্য প্রচুর ওভারহেড সরিয়ে ফেলার পরে প্রকৃত গতির পার্থক্য 70% (বা আরও বেশি) এর কাছাকাছি।
অবজেক্ট সৃষ্টি না ভুল। এক-বর্ণের স্ট্রিং ক্যাশে হওয়ায় কোনও পদ্ধতিই একটি নতুন অবজেক্ট তৈরি করে না।
পার্থক্যটি অকাট্য, তবে স্ট্রিং ইনডেক্সিংয়ের ক্ষেত্রে বৃহত্তর সংখ্যক চেকগুলি থেকে তৈরি করা হয়েছে, প্রকার এবং সুগঠনের ক্ষেত্রে। এটি কী প্রত্যাবর্তন করবে তা যাচাই করার প্রয়োজনের জন্য এটি বেশ সম্ভবত ধন্যবাদ thanks
তালিকা সূচক উল্লেখযোগ্যভাবে দ্রুত।
>>> python3 -m timeit '[x for x in "abc"]'
1000000 loops, best of 3: 0.388 usec per loop
>>> python3 -m timeit '[x for x in ["a", "b", "c"]]'
1000000 loops, best of 3: 0.436 usec per loop
আপনি যা খুঁজে পেয়েছেন তাতে এটি একমত নয় ...
আপনার অবশ্যই পাইথন 2 ব্যবহার করা উচিত।
>>> python2 -m timeit '[x for x in "abc"]'
1000000 loops, best of 3: 0.309 usec per loop
>>> python2 -m timeit '[x for x in ["a", "b", "c"]]'
1000000 loops, best of 3: 0.212 usec per loop
আসুন সংস্করণগুলির মধ্যে পার্থক্যটি ব্যাখ্যা করুন। আমি সংকলিত কোড পরীক্ষা করব।
পাইথন 3 এর জন্য:
import dis
def list_iterate():
[item for item in ["a", "b", "c"]]
dis.dis(list_iterate)
#>>> 4 0 LOAD_CONST 1 (<code object <listcomp> at 0x7f4d06b118a0, file "", line 4>)
#>>> 3 LOAD_CONST 2 ('list_iterate.<locals>.<listcomp>')
#>>> 6 MAKE_FUNCTION 0
#>>> 9 LOAD_CONST 3 ('a')
#>>> 12 LOAD_CONST 4 ('b')
#>>> 15 LOAD_CONST 5 ('c')
#>>> 18 BUILD_LIST 3
#>>> 21 GET_ITER
#>>> 22 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
#>>> 25 POP_TOP
#>>> 26 LOAD_CONST 0 (None)
#>>> 29 RETURN_VALUE
def string_iterate():
[item for item in "abc"]
dis.dis(string_iterate)
#>>> 21 0 LOAD_CONST 1 (<code object <listcomp> at 0x7f4d06b17150, file "", line 21>)
#>>> 3 LOAD_CONST 2 ('string_iterate.<locals>.<listcomp>')
#>>> 6 MAKE_FUNCTION 0
#>>> 9 LOAD_CONST 3 ('abc')
#>>> 12 GET_ITER
#>>> 13 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
#>>> 16 POP_TOP
#>>> 17 LOAD_CONST 0 (None)
#>>> 20 RETURN_VALUE
আপনি এখানে দেখুন যে তালিকাটি প্রতিবার তালিকা তৈরির কারণে ধীর হয়ে যাওয়ার সম্ভাবনা রয়েছে।
এই
9 LOAD_CONST 3 ('a')
12 LOAD_CONST 4 ('b')
15 LOAD_CONST 5 ('c')
18 BUILD_LIST 3
অংশ। স্ট্রিং ভেরিয়েন্টটিতে কেবল রয়েছে
9 LOAD_CONST 3 ('abc')
আপনি এটি পরীক্ষা করতে পারেন যে এটি কোনও পার্থক্য বলে মনে হচ্ছে:
def string_iterate():
[item for item in ("a", "b", "c")]
dis.dis(string_iterate)
#>>> 35 0 LOAD_CONST 1 (<code object <listcomp> at 0x7f4d068be660, file "", line 35>)
#>>> 3 LOAD_CONST 2 ('string_iterate.<locals>.<listcomp>')
#>>> 6 MAKE_FUNCTION 0
#>>> 9 LOAD_CONST 6 (('a', 'b', 'c'))
#>>> 12 GET_ITER
#>>> 13 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
#>>> 16 POP_TOP
#>>> 17 LOAD_CONST 0 (None)
#>>> 20 RETURN_VALUE
এটি কেবল উত্পাদন করে
9 LOAD_CONST 6 (('a', 'b', 'c'))
হিসাবে tuples অপরিবর্তনীয়। টেস্ট:
>>> python3 -m timeit '[x for x in ("a", "b", "c")]'
1000000 loops, best of 3: 0.369 usec per loop
দুর্দান্ত, গতিতে ব্যাক আপ।
পাইথন 2 এর জন্য:
def list_iterate():
[item for item in ["a", "b", "c"]]
dis.dis(list_iterate)
#>>> 2 0 BUILD_LIST 0
#>>> 3 LOAD_CONST 1 ('a')
#>>> 6 LOAD_CONST 2 ('b')
#>>> 9 LOAD_CONST 3 ('c')
#>>> 12 BUILD_LIST 3
#>>> 15 GET_ITER
#>>> >> 16 FOR_ITER 12 (to 31)
#>>> 19 STORE_FAST 0 (item)
#>>> 22 LOAD_FAST 0 (item)
#>>> 25 LIST_APPEND 2
#>>> 28 JUMP_ABSOLUTE 16
#>>> >> 31 POP_TOP
#>>> 32 LOAD_CONST 0 (None)
#>>> 35 RETURN_VALUE
def string_iterate():
[item for item in "abc"]
dis.dis(string_iterate)
#>>> 2 0 BUILD_LIST 0
#>>> 3 LOAD_CONST 1 ('abc')
#>>> 6 GET_ITER
#>>> >> 7 FOR_ITER 12 (to 22)
#>>> 10 STORE_FAST 0 (item)
#>>> 13 LOAD_FAST 0 (item)
#>>> 16 LIST_APPEND 2
#>>> 19 JUMP_ABSOLUTE 7
#>>> >> 22 POP_TOP
#>>> 23 LOAD_CONST 0 (None)
#>>> 26 RETURN_VALUE
বিজোড় বিষয়টি হল আমাদের তালিকার একই বিল্ডিং রয়েছে তবে এটি এখনও এটির জন্য দ্রুত। পাইথন 2 অদ্ভুত দ্রুত অভিনয় করছে।
আসুন বুঝতে এবং পুনরায় সময় মুছে ফেলা যাক। _ =
এটা অপ্টিমাইজ পেয়ে প্রতিরোধ করা হয়।
>>> python3 -m timeit '_ = ["a", "b", "c"]'
10000000 loops, best of 3: 0.0707 usec per loop
>>> python3 -m timeit '_ = "abc"'
100000000 loops, best of 3: 0.0171 usec per loop
আমরা দেখতে পাচ্ছি যে সংস্করণগুলির মধ্যে পার্থক্য (সেই সংখ্যাগুলি ছোট) এর জন্য অ্যাকাউন্টিং করার জন্য সূচনাটি যথেষ্ট তাত্পর্যপূর্ণ নয়! আমরা এভাবে উপসংহারে পৌঁছাতে পারি যে পাইথন 3 এর ধীরে ধীরে উপলব্ধি রয়েছে। এটি পাইথন 3 হিসাবে নিরাপদ স্কোপিংয়ের জন্য উপলব্ধিগুলি পরিবর্তন করে sense
ঠিক আছে, এখন মানদণ্ডকে উন্নত করুন (আমি কেবল ওভারহেড অপসারণ করছি যা পুনরাবৃত্তি নয়)। এটি পূর্বে বরাদ্দের মাধ্যমে পুনরাবৃত্তের বিল্ডিং সরিয়ে দেয়:
>>> python3 -m timeit -s 'iterable = "abc"' '[x for x in iterable]'
1000000 loops, best of 3: 0.387 usec per loop
>>> python3 -m timeit -s 'iterable = ["a", "b", "c"]' '[x for x in iterable]'
1000000 loops, best of 3: 0.368 usec per loop
>>> python2 -m timeit -s 'iterable = "abc"' '[x for x in iterable]'
1000000 loops, best of 3: 0.309 usec per loop
>>> python2 -m timeit -s 'iterable = ["a", "b", "c"]' '[x for x in iterable]'
10000000 loops, best of 3: 0.164 usec per loop
কল iter
করা ওভারহেড কিনা তা আমরা পরীক্ষা করতে পারি :
>>> python3 -m timeit -s 'iterable = "abc"' 'iter(iterable)'
10000000 loops, best of 3: 0.099 usec per loop
>>> python3 -m timeit -s 'iterable = ["a", "b", "c"]' 'iter(iterable)'
10000000 loops, best of 3: 0.1 usec per loop
>>> python2 -m timeit -s 'iterable = "abc"' 'iter(iterable)'
10000000 loops, best of 3: 0.0913 usec per loop
>>> python2 -m timeit -s 'iterable = ["a", "b", "c"]' 'iter(iterable)'
10000000 loops, best of 3: 0.0854 usec per loop
না, না। পার্থক্যটি খুব সামান্য, বিশেষত পাইথন 3 এর জন্য।
তাহলে আসুন আরও বেশি অযাচিত ওভারহেড সরিয়ে ফেলা যাক ... পুরো জিনিসটি ধীর করে দিয়ে! উদ্দেশ্যটি কেবল দীর্ঘতর পুনরাবৃত্তি হওয়া যাতে সময় ওভারহেড লুকায়।
>>> python3 -m timeit -s 'import random; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' '[x for x in iterable]'
100 loops, best of 3: 3.12 msec per loop
>>> python3 -m timeit -s 'import random; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' '[x for x in iterable]'
100 loops, best of 3: 2.77 msec per loop
>>> python2 -m timeit -s 'import random; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' '[x for x in iterable]'
100 loops, best of 3: 2.32 msec per loop
>>> python2 -m timeit -s 'import random; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' '[x for x in iterable]'
100 loops, best of 3: 2.09 msec per loop
এটি আসলে খুব বেশি পরিবর্তন হয়নি , তবে এটি কিছুটা সাহায্য করেছে।
সুতরাং বোধগম্যতা সরান। এটি ওভারহেড যা প্রশ্নের অংশ নয়:
>>> python3 -m timeit -s 'import random; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' 'for x in iterable: pass'
1000 loops, best of 3: 1.71 msec per loop
>>> python3 -m timeit -s 'import random; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'for x in iterable: pass'
1000 loops, best of 3: 1.36 msec per loop
>>> python2 -m timeit -s 'import random; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' 'for x in iterable: pass'
1000 loops, best of 3: 1.27 msec per loop
>>> python2 -m timeit -s 'import random; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'for x in iterable: pass'
1000 loops, best of 3: 935 usec per loop
ওটা অনেকটা এটার মতই! deque
পুনরাবৃত্তি করতে ব্যবহার করে আমরা কিছুটা দ্রুত এগিয়ে যেতে পারি । এটি মূলত একই, তবে এটি দ্রুত :
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 777 usec per loop
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 405 usec per loop
>>> python2 -m timeit -s 'import random; from collections import deque; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 805 usec per loop
>>> python2 -m timeit -s 'import random; from collections import deque; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 438 usec per loop
আমাকে যেটা প্রভাবিত করেছে তা হ'ল ইউনিকোড বাইটস্ট্রিংয়ের সাথে প্রতিযোগিতামূলক। আমরা চেষ্টা করে bytes
এবং unicode
উভয়েই স্পষ্ট করে এটি পরীক্ষা করতে পারি :
bytes
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = b"".join(chr(random.randint(0, 127)).encode("ascii") for _ in range(100000))' 'deque(iterable, maxlen=0)' :(
1000 loops, best of 3: 571 usec per loop
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = [chr(random.randint(0, 127)).encode("ascii") for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 394 usec per loop
>>> python2 -m timeit -s 'import random; from collections import deque; iterable = b"".join(chr(random.randint(0, 127)) for _ in range(100000))' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 757 usec per loop
>>> python2 -m timeit -s 'import random; from collections import deque; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 438 usec per loop
এখানে আপনি পাইথন 3 দেখতে পাইথন 2 এর চেয়ে আসলে দ্রুত ।
unicode
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = u"".join( chr(random.randint(0, 127)) for _ in range(100000))' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 800 usec per loop
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = [ chr(random.randint(0, 127)) for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 394 usec per loop
>>> python2 -m timeit -s 'import random; from collections import deque; iterable = u"".join(unichr(random.randint(0, 127)) for _ in range(100000))' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 1.07 msec per loop
>>> python2 -m timeit -s 'import random; from collections import deque; iterable = [unichr(random.randint(0, 127)) for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 469 usec per loop
আবার পাইথন 3 দ্রুততর, যদিও এটি প্রত্যাশিত str
ছিল ( পাইথন 3 তে তার বেশ মনোযোগ ছিল)।
আসলে, এটি unicode
- bytes
পার্থক্যটি খুব সামান্য, যা চিত্তাকর্ষক।
সুতরাং আসুন এটি একটি ক্ষেত্রে বিশ্লেষণ করি, কারণ এটি আমার পক্ষে দ্রুত এবং সুবিধাজনক:
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 777 usec per loop
>>> python3 -m timeit -s 'import random; from collections import deque; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'deque(iterable, maxlen=0)'
1000 loops, best of 3: 405 usec per loop
আমরা আসলে টিম পিটারের 10-বার-উত্তোলিত উত্তরটি বাতিল করতে পারি!
>>> foo = iterable[123]
>>> iterable[36] is foo
True
এগুলো নতুন জিনিস নয়!
তবে এটি উল্লেখযোগ্য: ইনডেক্সিং ব্যয় । পার্থক্যটি সম্ভবত সূচকের মধ্যে থাকবে, সুতরাং পুনরাবৃত্তিটি সরিয়ে ফেলুন এবং কেবল সূচক:
>>> python3 -m timeit -s 'import random; iterable = "".join(chr(random.randint(0, 127)) for _ in range(100000))' 'iterable[123]'
10000000 loops, best of 3: 0.0397 usec per loop
>>> python3 -m timeit -s 'import random; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'iterable[123]'
10000000 loops, best of 3: 0.0374 usec per loop
পার্থক্যটি সামান্য বলে মনে হচ্ছে, তবে ব্যয়ের অন্তত অর্ধেক ওভারহেড:
>>> python3 -m timeit -s 'import random; iterable = [chr(random.randint(0, 127)) for _ in range(100000)]' 'iterable; 123'
100000000 loops, best of 3: 0.0173 usec per loop
সুতরাং গতির পার্থক্য এটি দোষী করার সিদ্ধান্ত নিতে যথেষ্ট। আমি মনে করি.
তাহলে এত দ্রুত তালিকাকে কেন তালিকাভুক্ত করা হচ্ছে?
ঠিক আছে, আমি এটিতে আপনার কাছে ফিরে আসব, তবে আমার অনুমান যে এটি অভ্যন্তরীণ স্ট্রিংগুলি (বা ক্যাশেড অক্ষরগুলি এটি একটি পৃথক প্রক্রিয়াধীন হলে) পরীক্ষা করতে পারে to এটি সর্বোত্তমের চেয়ে কম দ্রুত হবে। তবে আমি উত্স পরীক্ষা করতে যাব (যদিও আমি সি ... এ স্বাচ্ছন্দ্যবোধ করি না)) :)।
সুতরাং এখানে উত্স:
static PyObject *
unicode_getitem(PyObject *self, Py_ssize_t index)
{
void *data;
enum PyUnicode_Kind kind;
Py_UCS4 ch;
PyObject *res;
if (!PyUnicode_Check(self) || PyUnicode_READY(self) == -1) {
PyErr_BadArgument();
return NULL;
}
if (index < 0 || index >= PyUnicode_GET_LENGTH(self)) {
PyErr_SetString(PyExc_IndexError, "string index out of range");
return NULL;
}
kind = PyUnicode_KIND(self);
data = PyUnicode_DATA(self);
ch = PyUnicode_READ(kind, data, index);
if (ch < 256)
return get_latin1_char(ch);
res = PyUnicode_New(1, ch);
if (res == NULL)
return NULL;
kind = PyUnicode_KIND(res);
data = PyUnicode_DATA(res);
PyUnicode_WRITE(kind, data, 0, ch);
assert(_PyUnicode_CheckConsistency(res, 1));
return res;
}
উপরে থেকে হাঁটা, আমাদের কিছু চেক থাকবে। এগুলি বিরক্তিকর। তারপরে কিছু অ্যাসাইনমেন্ট, যা বোরিং হওয়া উচিত। প্রথম আকর্ষণীয় লাইন হয়
ch = PyUnicode_READ(kind, data, index);
তবে আমরা আশা করব যে এটি দ্রুত, কারণ আমরা এটি একটি সূচকযুক্ত সি অ্যারে থেকে সূচকে পড়ছি। ফলাফলটি, ch
256 এরও কম হবে সুতরাং আমরা ক্যাশেড চরিত্রটিকে ফিরিয়ে দেব get_latin1_char(ch)
।
সুতরাং আমরা চালাব (প্রথম চেকগুলি বাদ দিচ্ছি)
kind = PyUnicode_KIND(self);
data = PyUnicode_DATA(self);
ch = PyUnicode_READ(kind, data, index);
return get_latin1_char(ch);
কোথায়
#define PyUnicode_KIND(op) \
(assert(PyUnicode_Check(op)), \
assert(PyUnicode_IS_READY(op)), \
((PyASCIIObject *)(op))->state.kind)
(যা উদ্বেগজনক কারণ ডিবাগগুলিতে দৃser়তাগুলি অবহেলিত হয়ে পড়েছে [যাতে আমি তা পরীক্ষা করে দেখতে পারি যে তারা দ্রুত)] এবং ((PyASCIIObject *)(op))->state.kind)
এটি (আমার মনে হয়) ইন্ডিয়ারেশন এবং সি-লেভেল কাস্ট);
#define PyUnicode_DATA(op) \
(assert(PyUnicode_Check(op)), \
PyUnicode_IS_COMPACT(op) ? _PyUnicode_COMPACT_DATA(op) : \
_PyUnicode_NONCOMPACT_DATA(op))
(যা ম্যাক্রোগুলি ( Something_CAPITALIZED
) সমস্ত দ্রুত) ধরে রেখে অনুরূপ কারণে বিরক্তিকর হয়),
#define PyUnicode_READ(kind, data, index) \
((Py_UCS4) \
((kind) == PyUnicode_1BYTE_KIND ? \
((const Py_UCS1 *)(data))[(index)] : \
((kind) == PyUnicode_2BYTE_KIND ? \
((const Py_UCS2 *)(data))[(index)] : \
((const Py_UCS4 *)(data))[(index)] \
) \
))
(যার মধ্যে সূচকগুলি জড়িত তবে আসলেই ধীর হয় না) এবং
static PyObject*
get_latin1_char(unsigned char ch)
{
PyObject *unicode = unicode_latin1[ch];
if (!unicode) {
unicode = PyUnicode_New(1, ch);
if (!unicode)
return NULL;
PyUnicode_1BYTE_DATA(unicode)[0] = ch;
assert(_PyUnicode_CheckConsistency(unicode, 1));
unicode_latin1[ch] = unicode;
}
Py_INCREF(unicode);
return unicode;
}
যা আমার সন্দেহকে নিশ্চিত করে যে:
এটি ক্যাশেড:
PyObject *unicode = unicode_latin1[ch];
এটি দ্রুত হওয়া উচিত। if (!unicode)
চলবে না হয়, তাই এটি এই ক্ষেত্রে আক্ষরিক সমতুল্য
PyObject *unicode = unicode_latin1[ch];
Py_INCREF(unicode);
return unicode;
সত্যই, পরীক্ষাগুলি assert
দ্রুত হওয়ার পরে (এগুলি অক্ষম করে [আমার মনে হয় এটি সি-লেভেল জোর দিয়ে কাজ করে ...]), কেবলমাত্র ধীর-ধীর অংশগুলি হ'ল:
PyUnicode_IS_COMPACT(op)
_PyUnicode_COMPACT_DATA(op)
_PyUnicode_NONCOMPACT_DATA(op)
কোনটি:
#define PyUnicode_IS_COMPACT(op) \
(((PyASCIIObject*)(op))->state.compact)
(দ্রুত, আগের মত),
#define _PyUnicode_COMPACT_DATA(op) \
(PyUnicode_IS_ASCII(op) ? \
((void*)((PyASCIIObject*)(op) + 1)) : \
((void*)((PyCompactUnicodeObject*)(op) + 1)))
(ম্যাক্রো দ্রুত হলে IS_ASCII
দ্রুত), এবং
#define _PyUnicode_NONCOMPACT_DATA(op) \
(assert(((PyUnicodeObject*)(op))->data.any), \
((((PyUnicodeObject *)(op))->data.any)))
(দ্রুত হিসাবে এটি একটি প্রতিস্থাপন প্লাস একটি ইন্ডিরিশন প্লাস একটি কাস্ট)।
সুতরাং আমরা নীচে (খরগোশের গর্ত) এর নিচে:
PyUnicode_IS_ASCII
যা হলো
#define PyUnicode_IS_ASCII(op) \
(assert(PyUnicode_Check(op)), \
assert(PyUnicode_IS_READY(op)), \
((PyASCIIObject*)op)->state.ascii)
হুম ... খুব দ্রুত মনে হচ্ছে ...
ঠিক আছে, তবে এর সাথে এর তুলনা করা যাক PyList_GetItem
। (হ্যাঁ, আমাকে আরও কাজ দেওয়ার জন্য টিম পিটার্সকে ধন্যবাদ : পি।)
PyObject *
PyList_GetItem(PyObject *op, Py_ssize_t i)
{
if (!PyList_Check(op)) {
PyErr_BadInternalCall();
return NULL;
}
if (i < 0 || i >= Py_SIZE(op)) {
if (indexerr == NULL) {
indexerr = PyUnicode_FromString(
"list index out of range");
if (indexerr == NULL)
return NULL;
}
PyErr_SetObject(PyExc_IndexError, indexerr);
return NULL;
}
return ((PyListObject *)op) -> ob_item[i];
}
আমরা দেখতে পাচ্ছি যে অ-ত্রুটিযুক্ত মামলায় এটি কেবল চলতে চলেছে:
PyList_Check(op)
Py_SIZE(op)
((PyListObject *)op) -> ob_item[i]
কোথায় PyList_Check
আছে
#define PyList_Check(op) \
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS)
( ট্যাবস! ট্যাবস !!! ) ( ইস্যু 21587 ) এটি 5 মিনিটের মধ্যে সংশোধন হয়ে একীভূত হয়ে গেছে । যেমন ... হ্যাঁ অভিশাপ। তারা স্কিটকে লজ্জায় ফেলেছিল।
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
#define PyType_FastSubclass(t,f) PyType_HasFeature(t,f)
#ifdef Py_LIMITED_API
#define PyType_HasFeature(t,f) ((PyType_GetFlags(t) & (f)) != 0)
#else
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
#endif
সুতরাং এটি সাধারণত সত্যই তুচ্ছ (দুটি ইন্ডিয়ারেশন এবং কয়েক বুলিয়ান চেক) যদি না Py_LIMITED_API
থাকে তবে কোন ক্ষেত্রে ... ???
তারপরে ইনডেক্সিং এবং একটি কাস্ট আছে ( ((PyListObject *)op) -> ob_item[i]
) এবং আমরা সম্পন্ন করেছি।
সুতরাং তালিকার জন্য অবশ্যই চেক কম রয়েছে এবং ছোট গতির পার্থক্য অবশ্যই বোঝায় যে এটি প্রাসঙ্গিক হতে পারে।
আমি সাধারণভাবে মনে করি, (->)
ইউনিকোডের জন্য আরও আরও টাইপ-চেকিং এবং ইন্ডিরিয়ারেশন রয়েছে। মনে হচ্ছে আমি একটা পয়েন্ট মিস করছি, তবে কী ?