আমি দেরী করছি কিন্তু, আপনি কি আপনার উত্তর দিয়ে কিছু উত্স চান? আমি চেষ্টা করব এবং এটি একটি প্রাথমিক উপায়ে শব্দ করব যাতে আরও লোকেরা অনুসরণ করতে পারে।
সিপিথন সম্পর্কে একটি ভাল বিষয় হ'ল আপনি এটির জন্য উত্সটি দেখতে পাচ্ছেন। আমি 3.5 রিলিজের জন্য লিঙ্কগুলি ব্যবহার করতে যাচ্ছি , তবে সংশ্লিষ্ট 2.x এর সন্ধান করা তুচ্ছ।
CPython সালে সি-এপিআই ফাংশন যা হ্যান্ডলগুলি একটি নতুন তৈরি int
অবজেক্ট PyLong_FromLong(long v)
। এই ফাংশনটির জন্য বিবরণটি হ'ল:
বর্তমান বাস্তবায়ন -5 এবং 256 এর মধ্যে সমস্ত পূর্ণসংখ্যার জন্য পূর্ণসংখ্যার অবজেক্টগুলির একটি অ্যারে রাখে, আপনি যখন এই পরিসীমাটিতে কোনও int তৈরি করেন আপনি বাস্তবে কেবল বিদ্যমান অবজেক্টের একটি রেফারেন্স ফিরে পাবেন । সুতরাং 1 টির মান পরিবর্তন করা উচিত I আমি সন্দেহ করি যে ক্ষেত্রে পাইথনের আচরণ অপরিজ্ঞাত। :-)
(আমার তির্যক)
আপনার সম্পর্কে জানেন না তবে আমি এটি দেখতে এবং মনে করি: আসুন সেই অ্যারেটি খুঁজে বার করুন!
আপনি সিপিথন সি কোড প্রয়োগকারী সি কোডের সাথে ঝাঁকুনি না থাকলে আপনার উচিত ; সবকিছু বেশ সুসংহত এবং পাঠযোগ্য। আমাদের ক্ষেত্রে, আমাদের মূল উত্স কোড ডিরেক্টরি গাছের Objects
উপ - ডিরেক্টরিতে সন্ধান করা উচিত ।
PyLong_FromLong
long
অবজেক্টগুলির সাথে ডিল করে যাতে আমাদের ভিতরে উঁকি দেওয়ার দরকার অনুমান করা শক্ত হওয়া উচিত নয় longobject.c
। ভিতরে দেখার পরে আপনি ভাবতে পারেন বিষয়গুলি বিশৃঙ্খল; সেগুলি রয়েছে তবে ভয় পাবেন না, আমরা যে ফাংশনটি সন্ধান করছি তা 230 লাইনে শীতল হওয়া আমাদের এটি দেখার জন্য অপেক্ষা করছে। এটি একটি ছোট্ট ফাংশন তাই মূল শরীরটি (ঘোষণা বাদে) সহজেই এখানে আটকানো হয়:
PyObject *
PyLong_FromLong(long ival)
{
// omitting declarations
CHECK_SMALL_INT(ival);
if (ival < 0) {
/* negate: cant write this as abs_ival = -ival since that
invokes undefined behaviour when ival is LONG_MIN */
abs_ival = 0U-(unsigned long)ival;
sign = -1;
}
else {
abs_ival = (unsigned long)ival;
}
/* Fast path for single-digit ints */
if (!(abs_ival >> PyLong_SHIFT)) {
v = _PyLong_New(1);
if (v) {
Py_SIZE(v) = sign;
v->ob_digit[0] = Py_SAFE_DOWNCAST(
abs_ival, unsigned long, digit);
}
return (PyObject*)v;
}
এখন, আমরা কোনও সি -মাস্টার-কোড-হ্যাক্সক্সোরজ নই তবে আমরা বোবাও নই, আমরা দেখতে পাচ্ছি যে CHECK_SMALL_INT(ival);
আমাদের সকলকে প্রলোভনমূলকভাবে উঁকি দিচ্ছে ; এর সাথে কিছু করার আছে আমরা বুঝতে পারি। আসুন এটি পরীক্ষা করে দেখুন:
#define CHECK_SMALL_INT(ival) \
do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \
return get_small_int((sdigit)ival); \
} while(0)
সুতরাং এটি ম্যাক্রো যা ফাংশনকে কল করে get_small_int
যদি মানটি ival
শর্তটি পূরণ করে:
if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS)
তাই কি হয় NSMALLNEGINTS
এবং NSMALLPOSINTS
? ম্যাক্রো! তারা এখানে :
#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS 257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS 5
#endif
সুতরাং আমাদের অবস্থা if (-5 <= ival && ival < 257)
কলget_small_int
।
এর আসুন এর get_small_int
সমস্ত গৌরবটি দেখি (ভাল, আমরা কেবল তার শরীরের দিকে নজর দেব কারণ আকর্ষণীয় জিনিসগুলি এখানে):
PyObject *v;
assert(-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS);
v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);
ঠিক আছে, একটি ঘোষণা করুন PyObject
, পূর্ববর্তী শর্তটি অ্যাসাইনমেন্টটি কার্যকর করে তা কার্যকর করুন:
v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
small_ints
দেখতে অনেকটা অ্যারের মতো দেখতে আমরা অনুসন্ধান করেছিলাম, এবং এটি! আমরা কেবল অভিশাপের ডকুমেন্টেশনটি পড়তে পারতাম এবং আমরা সবই জানতাম! :
/* Small integers are preallocated in this array so that they
can be shared.
The integers that are preallocated are those in the range
-NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
হ্যাঁ, এই আমাদের লোক। আপনি যখন int
পরিসরে একটি নতুন তৈরি করতে চান[NSMALLNEGINTS, NSMALLPOSINTS)
কেবল পূর্বনির্ধারিত অবস্থায় থাকা একটি ইতিমধ্যে বিদ্যমান অবজেক্টের একটি রেফারেন্স ফিরে পাবেন।
যেহেতু রেফারেন্সটি একই অবজেক্টকে বোঝায়, id()
সরাসরি জারি করা বা সাথে পরিচয় চেক করাis
এটির ঠিক একই জিনিসটি ফিরে আসবে।
তবে, এগুলো কখন বরাদ্দ করা হয় ??
_PyLong_Init
পাইথনে ইনিশিয়েশন চলাকালীন খুশিতে একটি লুপের জন্য প্রবেশ করবে আপনার জন্য এটি করুন:
for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++, v++) {
লুপ বডি পড়তে উত্সটি দেখুন!
আমি আশা করি আমার ব্যাখ্যা আপনাকে স্পষ্টত সি জিনিস তৈরি করেছে (শাস্তি স্পষ্টভাবে উদ্দেশ্যযুক্ত)।
কিন্তু 257 is 257
,? কি খবর?
এটি ব্যাখ্যা করা আসলে সহজ, এবং আমি ইতিমধ্যে এটি করার চেষ্টা করেছি ; পাইথন এই ইন্টারেক্টিভ স্টেটমেন্টটিকে একক ব্লক হিসাবে কার্যকর করবে এই কারণে এটি ঘটে:
>>> 257 is 257
এই বিবৃতিটির প্রশংসা করার সময়, সিপিথন দেখতে পাবে যে আপনার দুটি মিল রয়েছে ral PyLongObject
প্রতিনিধিত্বকারী257
। আপনি নিজেই এই সংকলনটি করতে এবং এর বিষয়বস্তুগুলি পরীক্ষা করে দেখতে পারেন:
>>> codeObj = compile("257 is 257", "blah!", "exec")
>>> codeObj.co_consts
(257, None)
সিপিথন যখন অপারেশন করে, এটি এখন ঠিক একই জিনিসটি লোড করতে চলেছে:
>>> import dis
>>> dis.dis(codeObj)
1 0 LOAD_CONST 0 (257) # dis
3 LOAD_CONST 0 (257) # dis again
6 COMPARE_OP 8 (is)
তাই is
ফিরে আসবে True
।