پوزیشنل آرگیومنٹس (位置引数) بائیں سے ترتیب وار ملائے جاتے ہیں، اس لیے a کو 1 اور b کو 3 ملتا ہے۔ b کی ڈیفالٹ ویلیو (デフォルト値) 2 ہے، لیکن چونکہ ویلیو پاس کی گئی ہے اس لیے اسی کو ترجیح ملتی ہے۔ جو 4 اور 5 کسی سے نہ مل سکے وہ ایک ستارے والے args میں ٹیوپل (タプル) کی شکل میں جمع ہو کر (4, 5) بن جاتے ہیں۔ کوئی بھی کی ورڈ آرگیومنٹ (キーワード引数) پاس نہیں کیا گیا، اس لیے kwargs خالی ڈکشنری {} ہوتی ہے، None نہیں۔ اگر آپ سمجھیں کہ b میں ڈیفالٹ ویلیو 2 باقی رہتی ہے تو نتیجہ (1, 2, (3, 4, 5), {}) بنتا ہے، لیکن پوزیشنل آرگیومنٹ کو ڈیفالٹ ویلیو پر ترجیح حاصل ہے۔ args میں جانے والی چیز لسٹ نہیں بلکہ ٹیوپل ہے، اس لیے یہ مربع بریکٹس کے ساتھ بھی ظاہر نہیں ہوتی۔
سوال 2 | کی ورڈ کے ذریعے بتانا
درج ذیل کال میں ایک ایسا نام کی ورڈ کے طور پر پاس کیا گیا جو تعریف میں موجود نہیں۔ کیا ظاہر ہوگا؟
پوزیشنل آرگیومنٹ (位置引数) کے طور پر صرف 1 دیا گیا ہے، اس لیے a کو 1 ملتا ہے، اور چونکہ b نہیں دیا گیا اس لیے وہ اپنی ڈیفالٹ ویلیو 2 پر رہتا ہے۔ تعریف میں x نام کا کوئی پیرامیٹر (仮引数) نہیں، اس لیے کی ورڈ آرگیومنٹ (キーワード引数) x=9 دو ستاروں والے kwargs میں {'x': 9} کی شکل میں چلا جاتا ہے۔ کوئی پوزیشنل آرگیومنٹ بچا نہیں، اس لیے args خالی ٹیوپل () ہوتا ہے۔ اگر آپ سمجھیں کہ x=9 b میں جاتا ہے تو نتیجہ (1, 9, (), {}) بنتا ہے، لیکن کی ورڈ آرگیومنٹ صرف اسی پیرامیٹر میں جاتا ہے جس کا نام میل کھاتا ہو۔ اگر آپ سمجھیں کہ 9 args میں جاتا ہے تو نتیجہ (1, 2, (9,), {}) بنتا ہے، لیکن نام کے ساتھ پاس کی گئی ویلیو کبھی بچے ہوئے پوزیشنل آرگیومنٹس میں نہیں جاتی۔ اگر یہ الٹ سمجھ لیا جائے کہ ایک ستارہ ڈکشنری اور دو ستارے ٹیوپل وصول کرتے ہیں تو ایسا لگے گا جیسے {'x': 9} args میں چلا گیا اور kwargs خالی رہ گئی۔
سوال 3 | ڈیفالٹ خالی لسٹ
ڈیفالٹ ویلیو کے طور پر خالی لسٹ لکھنے والے درج ذیل فنکشن کو 3 بار کال کیا گیا۔ ظاہر ہونے والی 3 لائنیں کون سی ہیں؟
اوپر سے نیچے ترتیب وار None / None / None ظاہر ہوتے ہیں
اوپر سے نیچے ترتیب وار [1] / [1, 2] / [1, 2, 3] ظاہر ہوتے ہیں
اوپر سے نیچے ترتیب وار [1] / [2] / [3] ظاہر ہوتے ہیں
اوپر سے نیچے ترتیب وار [1] / [1, 2] / [2, 3] ظاہر ہوتے ہیں
درست جوابB. اوپر سے نیچے ترتیب وار [1] / [1, 2] / [1, 2, 3] ظاہر ہوتے ہیں
ڈیفالٹ ویلیو (デフォルト値) [] صرف ایک بار، def والی لائن چلنے کے وقت، بنتی ہے اور وہی لسٹ فنکشن آبجیکٹ (関数オブジェクト) میں محفوظ ہو جاتی ہے۔ ہر کال پر نئی خالی لسٹ نہیں بنتی، اس لیے append کے نتائج اگلی کال تک باقی رہتے ہیں اور لسٹ [1]، [1, 2]، [1, 2, 3] کی طرح بڑھتی جاتی ہے۔ اگر آپ سمجھیں کہ ہر کال پر نئی لسٹ بنتی ہے تو [1] / [2] / [3] ملے گا، لیکن یہ رویہ تب ہوتا ہے جب ڈیفالٹ lst=None رکھ کر باڈی میں نئی لسٹ بنائی جائے۔ اگر غلطی سے باڈی میں return lst.append(x) لکھ دیا جائے تو append کی ریٹرن ویلیو None مسلسل 3 بار پرنٹ ہوگی۔ مزید یہ کہ اگر 3 لائنوں میں الگ الگ لکھنے کے بجائے ایک لائن میں print(add(1), add(2), add(3)) لکھا جائے تو تینوں ایک ہی لسٹ کی طرف اشارہ کرتے ہیں، اس لیے سب کی evaluation مکمل ہونے کے بعد کی حالت [1, 2, 3] مسلسل 3 بار پرنٹ ہوتی ہے۔
سوال 4 | ڈیفالٹ ویلیو کی شراکت
3 بار کال کرنے کے بعد فنکشن آبجیکٹ کا ایٹریبیوٹ ظاہر کیا گیا۔ کیا ظاہر ہوگا؟
فنکشن آبجیکٹ اپنی ڈیفالٹ ویلیوز __defaults__ نامی ایٹریبیوٹ (属性) میں ٹیوپل (タプル) کی شکل میں رکھتا ہے۔ پیرامیٹرز میں سے صرف lst کی ڈیفالٹ ویلیو ہے، اس لیے یہ ایک عنصر والا ٹیوپل بنتا ہے اور آخر میں کاما کے ساتھ ظاہر ہوتا ہے۔ اس کے اندر وہی لسٹ ہے جو def والی لائن پر صرف ایک بار بنی تھی، اور 3 کالز میں append کیے گئے نتائج اس میں جوں کے توں باقی ہیں، اس لیے یہ ([1, 2, 3],) بنتا ہے۔ ایک بار بھی کال نہ کرنے کی حالت میں یہ ([],) ہوتا، لیکن کالز کا اثر یہاں ظاہر ہو جانا ہی میوٹیبل ڈیفالٹ آرگیومنٹ (ミュータブルなデフォルト引数) کا خطرناک پہلو ہے۔ __defaults__ خود ٹیوپل ہے اس لیے مربع بریکٹس کے ساتھ ظاہر نہیں ہوتا، اور نہ ہی اس کے اندر کی لسٹ ٹیوپل میں بدلتی ہے۔
سوال 5 | ڈیفالٹ ویلیو کی evaluation
ڈیفالٹ ویلیو کے طور پر ایک ویری ایبل لکھا گیا، اور اس کے بعد اسی ویری ایبل کو دوبارہ ویلیو دی گئی۔ ظاہر ہونے والی 2 لائنیں کون سی ہیں؟
i = 5def h(x=i): return xi = 10print(h())print(h(i))
پہلے 5، پھر 5
پہلے 5، پھر 10
پہلے 10، پھر 10
پہلے 10، پھر 5
درست جوابB. پہلے 5، پھر 10
ڈیفالٹ ویلیو (デフォルト値) کا ایکسپریشن ہر بار فنکشن کال ہونے پر evaluate نہیں ہوتا؛ یہ صرف ایک بار، def والی لائن چلنے کے لمحے، evaluate ہوتا ہے۔ اس وقت i کی ویلیو 5 ہے، اس لیے فنکشن آبجیکٹ میں 5 محفوظ ہو جاتا ہے۔ بعد میں i کو 10 کر دینے سے بھی پہلے سے محفوظ ڈیفالٹ ویلیو نہیں بدلتی، اس لیے h() 5 لوٹاتا ہے۔ دوسری طرف h(i) کال کے لمحے i کو پڑھ کر پاس کرتا ہے، اس لیے اس وقت کی ویلیو 10 لوٹتی ہے۔ اگر آپ سمجھیں کہ ڈیفالٹ ویلیو ہر کال پر evaluate ہوتی ہے تو دونوں لائنیں 10 ہوں گی، اور اگر سمجھیں کہ آرگیومنٹ کے طور پر پاس کی گئی ویلیو بھی ڈیفالٹ ویلیو سے بدل جاتی ہے تو دونوں لائنیں 5 ہوں گی۔ میوٹیبل ڈیفالٹ آرگیومنٹ کا جال بھی اسی اصول سے پیدا ہوتا ہے۔
سوال 6 | آرگیومنٹس کی ترتیب
درج ذیل کوڈ کو فائل میں محفوظ کر کے python3 سے چلایا گیا۔ کیا ہوگا؟
def g(a=1, b):return a + bprint(g(2, 3))
تعریف کے مرحلے پر SyntaxError آتا ہے، اور ایک لائن بھی نہیں چلتی
4 ظاہر ہوتا ہے، اور پروگرام آخر تک معمول کے مطابق چلتا ہے
کال کے مرحلے پر TypeError آتا ہے، اور عمل وہیں رک جاتا ہے
5 ظاہر ہوتا ہے، اور پروگرام آخر تک معمول کے مطابق چلتا ہے
درست جوابA. تعریف کے مرحلے پر SyntaxError آتا ہے، اور ایک لائن بھی نہیں چلتی
ڈیفالٹ ویلیو والے پیرامیٹر (仮引数) کے بعد بغیر ڈیفالٹ ویلیو والا پیرامیٹر نہیں رکھا جا سکتا۔ یہ اصول سنٹیکس کے مرحلے پر جانچا جاتا ہے، اس لیے فائل چلاتے ہی سب سے پہلے SyntaxError آتا ہے اور parameter without a default follows parameter with a default والا پیغام دکھائی دیتا ہے (3.11 اور اس سے پہلے: non-default argument follows default argument)۔ چونکہ سنٹیکس کا تجزیہ (構文解析) چلانے سے پہلے پوری فائل پر ہوتا ہے، اس لیے print والی لائن سمیت ایک لائن بھی نہیں چلتی۔ یہ کال کرنے کے طریقے کی غلطی سے پیدا ہونے والے TypeError سے بالکل مختلف مرحلے کی پکڑ ہے۔ g(2, 3) بذاتِ خود پیرامیٹرز کی تعداد سے میل کھاتا ہے، اس لیے اگر تعریف درست ہوتی تو 5 ظاہر ہونا چاہیے تھا، لیکن وہاں تک پہنچا ہی نہیں جاتا۔ درست طریقہ یہ ہے کہ def g(b, a=1) کی طرح ڈیفالٹ ویلیو والے پیرامیٹر کو بعد میں رکھا جائے۔
سوال 7 | فنکشن کی ریٹرن ویلیو
return ہونے یا نہ ہونے میں مختلف دو فنکشنز کو اس طرح کال کیا گیا۔ کیا ظاہر ہوگا؟
one کبھی return سے گزرے بغیر ختم ہو جاتا ہے، اس لیے اس کی ریٹرن ویلیو (戻り値) None ہوتی ہے۔ خالی ٹیوپل یا خالی اسٹرنگ واپس نہیں آتی۔ two میں return کے بعد کاما سے 1 اور 2 لکھے گئے ہیں، لیکن یہ دو ویلیوز واپس کرنا نہیں بلکہ ایک ٹیوپل (タプル) (1, 2) واپس کرنا ہے۔ اس لیے type(two()).__name__ کا نتیجہ tuple ہے۔ اگر آپ سمجھیں کہ متعدد ریٹرن ویلیوز ایک لسٹ میں جمع ہو جاتی ہیں تو list ملے گا، لیکن کاما سے لکھا گیا ایکسپریشن ٹیوپل بناتا ہے۔ صرف کچھ ظاہر کرنے والے فنکشن کی ریٹرن ویلیو کو کسی ویری ایبل میں رکھ کر استعمال کرتے وقت جو مشکل پیش آتی ہے، اس کی وجہ اکثر یہی None ہوتا ہے۔
سوال 8 | کال میں ان پیکنگ
درج ذیل کوڈ لسٹ کے آگے ستارہ لگا کر فنکشن کو کال کرتا ہے۔ کیا ظاہر ہوگا؟
کال کرنے والی طرف لسٹ کے آگے ایک ستارہ لگانے سے اس کے اندر کی چیزیں ایک ایک کر کے پوزیشنل آرگیومنٹس (位置引数) کے طور پر بانٹ دی جاتی ہیں۔ چنانچہ a کو 1 اور b کو 2 ملتا ہے، اور بچا ہوا 3 ایک ستارے والے args میں ٹیوپل (タプル) کی شکل میں جمع ہو کر (3,) بن جاتا ہے۔ چونکہ یہ ایک عنصر والا ٹیوپل ہے، اس لیے آخر میں کاما لگتا ہے۔ کوئی کی ورڈ آرگیومنٹ پاس نہیں کیا گیا، اس لیے kwargs خالی ڈکشنری {} ہے، None نہیں۔ اگر ستارہ لگانا بھول کر f(vals) لکھ دیا جائے تو پوری لسٹ پہلے پیرامیٹر میں چلی جاتی ہے اور ([1, 2, 3], 2, (), {}) بنتا ہے، یعنی کوئی ایرر آئے بغیر صرف نتیجہ بدل جاتا ہے۔ args میں ٹیوپل جاتا ہے، اس لیے یہ مربع بریکٹس کے ساتھ بھی ظاہر نہیں ہوتا۔
سوال 9 | اینوٹیشنز کے ساتھ برتاؤ
درج ذیل فنکشن کو اس کی اینوٹیشن میں لکھی گئی ٹائپ سے مختلف ٹائپ کی ویلیو کے ساتھ کال کیا گیا۔ کیا ہوگا؟
لائن 1 پر 文字列 پرنٹ ہوتا ہے، اور لائن 2 پر <class 'int'> پرنٹ ہوتا ہے
لائن 1 پر TypeError آتا ہے، جو بتاتا ہے کہ اینوٹیشن سے مختلف ٹائپ پاس نہیں کی جا سکتی
لائن 1 پر 文字列 پرنٹ ہوتا ہے، اور لائن 2 پر int پرنٹ ہوتا ہے
لائن 1 پر ValueError آتا ہے، جو بتاتا ہے کہ اسے int میں تبدیل نہیں کیا جا سکتا
درست جوابA. لائن 1 پر 文字列 پرنٹ ہوتا ہے، اور لائن 2 پر <class 'int'> پرنٹ ہوتا ہے
اینوٹیشن (アノテーション) صرف فنکشن آبجیکٹ کی __annotations__ نامی ڈکشنری میں درج ہو جاتی ہے؛ رن ٹائم پر ٹائپ کی جانچ نہیں ہوتی۔ a کے لیے int لکھا ہونے کے باوجود آپ اسٹرنگ پاس کر سکتے ہیں، اور b کے لیے str لکھا ہونے کے باوجود انٹیجر پاس کر سکتے ہیں۔ ریٹرن ویلیو کے لیے bool لکھا ہونے کے باوجود حقیقت میں وہی اسٹرنگ جوں کی توں واپس آتی ہے جو وصول کی گئی تھی۔ اس لیے لائن 1 پر 文字列 جوں کا توں پرنٹ ہوتا ہے۔ لائن 2 پر __annotations__['a'] میں محفوظ چیز ٹائپ آبجیکٹ int ہے، اس لیے اسے پرنٹ کرنے پر یہ <class 'int'> کی شکل میں ظاہر ہوتا ہے۔ صرف 3 حروف int پرنٹ نہیں ہوتے۔ اگر آپ واقعی ٹائپس کی جانچ کرنا چاہتے ہیں تو آپ کو الگ ٹائپ چیکنگ ٹول استعمال کرنا ہوگا، یا باڈی میں خود جانچنا ہوگا۔
سوال 10 | ڈیفالٹ ویلیو کو درست کرنے کا طریقہ
درج ذیل کوڈ کو ڈیفالٹ ویلیو None رکھ کر دوبارہ لکھا گیا۔ ظاہر ہونے والی 3 لائنیں کون سی ہیں؟
def add2(x, lst=None): if lst is None:lst = []lst.append(x) return lstprint(add2(1))print(add2(2))print(add2(3, [9]))
اوپر سے نیچے ترتیب وار [1] / [1, 2] / [9, 3] ظاہر ہوتے ہیں
اوپر سے نیچے ترتیب وار [1] / [2] / [9, 3] ظاہر ہوتے ہیں
اوپر سے نیچے ترتیب وار [1] / [2] / [3, 9] ظاہر ہوتے ہیں
اوپر سے نیچے ترتیب وار [1] / [2] / [3] ظاہر ہوتے ہیں
درست جوابB. اوپر سے نیچے ترتیب وار [1] / [2] / [9, 3] ظاہر ہوتے ہیں
معیاری طریقہ یہ ہے کہ ڈیفالٹ ویلیو (デフォルト値) None رکھی جائے، پھر باڈی کے شروع میں جانچا جائے کہ آیا یہ None ہے، اور اگر ہو تو نئی خالی لسٹ بنائی جائے۔ چونکہ None ایک ناقابلِ تبدیلی ویلیو ہے، اس لیے صرف ایک بار evaluate ہونے کے باوجود شراکت کا مسئلہ پیدا نہیں ہوتا۔ پہلی اور دوسری کال میں، جن میں lst چھوڑ دیا گیا ہے، ہر بار نئی خالی لسٹ بنتی ہے، اس لیے پچھلی کال کا کوئی عنصر باقی رہے بغیر نتیجہ [1] اور [2] ہوتا ہے۔ تیسری کال میں کال کرنے والی طرف [9] پاس کرتی ہے، اس لیے lst is None غلط (False) ہو جاتا ہے، اور پاس کی گئی لسٹ کے آخر میں 3 جوڑ کر [9, 3] بنتا ہے۔ اگر دوبارہ لکھنے سے پہلے والا lst=[] ہی رہتا تو چھوڑی گئی دوسری کال میں پچھلی کال کے عناصر باقی رہ کر [1, 2] بنتا۔ اگر کال کرنے والی طرف کی پاس کردہ لسٹ کو نظرانداز کر کے ہمیشہ نئی لسٹ بنائی جائے تو [1] / [2] / [3] ملے گا، اور اس طریقے کا فائدہ — یعنی جب لسٹ دی جائے تو اسی کو استعمال کرنا — ضائع ہو جاتا ہے۔ اگر آخر میں جوڑنے کے بجائے insert(0, x) سے شروع میں داخل کیا جائے تو تیسری کال کا نتیجہ [3, 9] ہوگا۔
سوال 11 | نام تلاش کرنے کی ترتیب
Python کا LEGB اصول کسی ویری ایبل کے نام کو جس ترتیب سے تلاش کرتا ہے، ان میں درست ترتیب کون سی ہے؟
اس ترتیب سے: زیرِ عمل فنکشن، ماڈیول کی بالائی سطح، احاطہ کرنے والا فنکشن، بلٹ اِن
اس ترتیب سے: زیرِ عمل فنکشن، احاطہ کرنے والا فنکشن، ماڈیول کی بالائی سطح، بلٹ اِن
اس ترتیب سے: ماڈیول کی بالائی سطح، بلٹ اِن، زیرِ عمل فنکشن، احاطہ کرنے والا فنکشن
اس ترتیب سے: بلٹ اِن، ماڈیول کی بالائی سطح، احاطہ کرنے والا فنکشن، زیرِ عمل فنکشن
درست جوابB. اس ترتیب سے: زیرِ عمل فنکشن، احاطہ کرنے والا فنکشن، ماڈیول کی بالائی سطح، بلٹ اِن
LEGB دراصل Local، Enclosing، Global، Built-in کے ابتدائی حروف ہیں، اور یہ سب سے اندر سے باہر کی طرف تلاش کو ظاہر کرتا ہے۔ پہلے زیرِ عمل فنکشن کے اندر دیکھا جاتا ہے، پھر اسے گھیرنے والے بیرونی فنکشن کے اندر، پھر ماڈیول کی بالائی سطح (モジュール最上位) پر، اور آخر میں len اور print جیسے بلٹ اِن (組み込み) ناموں میں۔ کوئی چیز ملتے ہی تلاش ختم ہو جاتی ہے، اس لیے اگر اندر وہی نام استعمال ہو تو باہر والا نام چھپ جاتا ہے۔ اگر تلاش باہر سے اندر کی طرف ہوتی تو فنکشن کے اندر بنایا گیا لوکل ویری ایبل (ローカル変数) ماڈیول کی سطح کے ہم نام ویری ایبل سے ہار جاتا، جو اصل رویے سے میل نہیں کھاتا۔ Global اور Enclosing کی ترتیب الٹ دینے کی غلطی بھی عام ہے، لیکن احاطہ کرنے والا فنکشن ماڈیول کی بالائی سطح سے زیادہ اندر ہوتا ہے۔
سوال 12 | لوکل اسائنمنٹ
درج ذیل کوڈ میں فنکشن کے اندر اسی نام کو ویلیو اسائن کی گئی ہے جو باہر بھی موجود ہے۔ ظاہر ہونے والی 2 لائنیں کون سی ہیں؟
x = 'global'def f(): x = 'local'print(x)f()print(x)
پہلے local، پھر local
پہلے local، پھر global
پہلے global، پھر global
پہلے global، پھر local
درست جوابB. پہلے local، پھر global
فنکشن کے اندر کسی نام کو ویلیو اسائن کرنے سے وہ نام ایک نئے لوکل ویری ایبل (ローカル変数) کے طور پر بنتا ہے، اور ماڈیول کی سطح کا ہم نام ویری ایبل بالکل متاثر نہیں ہوتا۔ فنکشن کے اندر کا print(x) لوکل x پڑھتا ہے، اس لیے local پرنٹ ہوتا ہے، لیکن فنکشن سے واپس آنے کے بعد کا print(x) ماڈیول کی سطح کا x پڑھتا ہے، اس لیے global پرنٹ ہوتا ہے۔ اگر آپ سمجھیں کہ فنکشن کے اندر کی اسائنمنٹ باہر تک پہنچتی ہے تو دونوں لائنیں local ہوں گی، لیکن اس کے لیے فنکشن کے شروع میں global x کا اعلان ضروری ہے۔ اس کے برعکس اگر آپ سمجھیں کہ فنکشن کے اندر کی اسائنمنٹ نظرانداز ہو کر باہر کی ویلیو پڑھی جاتی ہے تو دونوں لائنیں global ہوں گی، لیکن اسائنمنٹ ہوتے ہی لوکل ویری ایبل واقعی بن جاتا ہے۔ یہ عدم توازن — پڑھنا باہر تک پہنچتا ہے مگر لکھنا نہیں — Python کے اسکوپ (スコープ) کا بنیادی اصول ہے۔
سوال 13 | nonlocal
درج ذیل کوڈ میں اندرونی فنکشن باہر والے ویری ایبل کو بدلنے کی کوشش کرتا ہے۔ کیا ظاہر ہوگا؟
outer کے اندر والے inner میں nonlocal n لکھا ہے، اس لیے n کو دی گئی ویلیو احاطہ کرنے والے فنکشن outer کے n تک پہنچتی ہے۔ inner کو کال کرنے کے بعد outer جو n لوٹاتا ہے وہ 2 ہے۔ outer2 کے اندر والے inner میں ایسا کوئی اعلان نہیں، اس لیے n = 2 صرف inner کا ایک نیا لوکل ویری ایبل (ローカル変数) بنا کر ختم ہو جاتا ہے، اور outer2 کا n بدستور 1 رہتا ہے۔ چنانچہ آؤٹ پٹ 2 1 ہے۔ اگر آپ سمجھیں کہ دونوں پہنچتے ہیں تو 2 2 ملے گا، اور اگر سمجھیں کہ کوئی نہیں پہنچتا تو 1 1 ملے گا، لیکن فرق صرف nonlocal کی اسی ایک لائن سے پیدا ہوتا ہے۔ یہ بھی یاد رکھیں کہ nonlocal تب تک استعمال نہیں ہو سکتا جب تک احاطہ کرنے والے فنکشن میں اسی نام کا ویری ایبل پہلے سے موجود نہ ہو، اور یہ ماڈیول کی بالائی سطح کے ویری ایبل کی طرف اشارہ بھی نہیں کر سکتا۔ بالائی سطح کا ویری ایبل بدلنا ہو تو global استعمال کریں۔
سوال 14 | Unbound ایرر
ایک نام جسے بعد والی لائن میں ویلیو دی جاتی ہے، اسے پہلے والی لائن میں پڑھا گیا۔ درج ذیل کوڈ چلانے پر کیا ہوگا؟
z = 100def bad():print(z)z = 1bad()
UnboundLocalError آتا ہے، کچھ بھی پرنٹ نہیں ہوتا، اور پروگرام رک جاتا ہے
100 پرنٹ ہوتا ہے، اور پروگرام آخر تک معمول کے مطابق چلتا ہے
None پرنٹ ہوتا ہے، اور پروگرام آخر تک معمول کے مطابق چلتا ہے
1 پرنٹ ہوتا ہے، اور پروگرام آخر تک معمول کے مطابق چلتا ہے
درست جوابA. UnboundLocalError آتا ہے، کچھ بھی پرنٹ نہیں ہوتا، اور پروگرام رک جاتا ہے
جب Python کسی فنکشن کی باڈی کو کمپائل کرتا ہے تو وہ ہر اس نام کو، جسے فنکشن میں کہیں بھی ویلیو اسائن کی گئی ہو، مکمل طور پر لوکل ویری ایبل (ローカル変数) قرار دے دیتا ہے۔ یہ فیصلہ پورے فنکشن کے لیے ہوتا ہے، اور لائنوں کی ترتیب سے کوئی فرق نہیں پڑتا۔ اس bad فنکشن میں بعد والی لائن پر z = 1 کی اسائنمنٹ ہے، اس لیے z کو اس فنکشن کا لوکل ویری ایبل سمجھا جاتا ہے۔ پھر print(z) کے مقام پر اس میں ابھی کوئی ویلیو نہیں ڈالی گئی، اس لیے UnboundLocalError آتا ہے۔ اس ایکسیپشن (例外) کے پیغام کے الفاظ Python کے ورژن کے لحاظ سے بدل سکتے ہیں، لیکن ٹائپ کا نام UnboundLocalError ہی رہتا ہے۔ بالائی سطح کا z = 100 حوالے میں نہیں آتا۔ اگر آپ سمجھیں کہ اسائنمنٹ سے پہلے کی لائن ہونے کی وجہ سے باہر کی ویلیو پڑھی جائے گی تو 100 ملے گا، لیکن Python اس طرح کام نہیں کرتا۔ نہ ہی بغیر ویلیو کا لوکل ویری ایبل None بنتا ہے۔
سوال 15 | global اعلان
درج ذیل کوڈ میں global اعلان والا ایک فنکشن اور بغیر اعلان والا ایک فنکشن ساتھ ساتھ رکھے گئے ہیں۔ کیا ظاہر ہوگا؟
n = 10def f(): global nn = 20 return ndef g():n = 30 return nprint(f(), g(), n)
20 30 30
20 30 20
20 30 10
10 30 10
درست جوابB. 20 30 20
f میں global n لکھا ہے، اس لیے n = 20 ماڈیول کی بالائی سطح (モジュール最上位) کا n بدل دیتا ہے۔ f خود 20 لوٹاتا ہے، اور بالائی سطح کا n بھی 20 ہو جاتا ہے۔ g میں ایسا کوئی اعلان نہیں، اس لیے n = 30 صرف g میں ایک لوکل ویری ایبل (ローカル変数) بناتا ہے اور بالائی سطح کے n پر اثر نہیں ڈالتا۔ g اپنا لوکل 30 لوٹاتا ہے۔ آخری print جو n پڑھتا ہے وہ بالائی سطح والا ہے، اور چونکہ f اسے پہلے ہی بدل چکا ہے، اس لیے وہ 20 ہے۔ اگر آپ سمجھیں کہ g کی اسائنمنٹ بھی باہر تک پہنچتی ہے تو 20 30 30 ملے گا، اور اگر سمجھیں کہ global کا کوئی اثر نہیں تو 20 30 10 ملے گا۔ global اعلان (global宣言) ایک ہدایت ہے کہ "اس نام کو دی گئی ویلیو بالائی سطح تک پہنچاؤ"؛ یاد رکھیں کہ اگر صرف ویلیو پڑھنی ہو تو اعلان کی ضرورت نہیں۔
سوال 16 | __all__ کا اثر
درج ذیل mymod.py تیار کی گئی، اور ایک دوسری فائل میں from mymod import * لکھا گیا۔ کون سے نام کال کرنے والی طرف لائے جاتے ہیں؟
درست جوابD. صرف pub لایا جاتا ہے، other اور hello نہیں
ستارے والا import عام طور پر ہر وہ نام لے آتا ہے جو انڈر اسکور سے شروع نہ ہو، لیکن اگر ماڈیول (モジュール) کی طرف __all__ نامی اسٹرنگز کی لسٹ موجود ہو تو صرف اسی میں درج ناموں تک محدود ہو جاتا ہے۔ اس مثال میں __all__ میں صرف pub درج ہے، اس لیے نہ other لایا جاتا ہے نہ hello۔ other انڈر اسکور سے شروع نہیں ہوتا، لیکن جب __all__ موجود ہو تو اس کی لسٹ کو ترجیح ملتی ہے۔ فنکشن ہونے کی وجہ سے بھی کوئی خاص سلوک نہیں ہوتا، اس لیے hello بھی اسی طرح نہیں لایا جاتا۔ __all__ کا اثر صرف ستارے والے import پر ہوتا ہے؛ from mymod import hello کی طرح کسی مخصوص نام کا import، یا import mymod کے بعد mymod.hello() لکھنے کا طریقہ نہیں رکتا۔
سوال 17 | __name__ کی ویلیو
درج ذیل mymod2.py کو python3 mymod2.py سے براہِ راست چلانے پر، اور دوسری فائل سے import mymod2 کرنے پر، __name__ کی ویلیوز کا درست جوڑا کون سا ہے؟
براہِ راست چلانے پر mymod2، اور import پر __main__
براہِ راست چلانے اور import دونوں پر __main__
براہِ راست چلانے پر __main__، اور import پر mymod2
براہِ راست چلانے اور import دونوں پر mymod2
درست جوابC. براہِ راست چلانے پر __main__، اور import پر mymod2
جب آپ کسی فائل کو python3 سے براہِ راست چلاتے ہیں تو __name__ میں '__main__' رکھا جاتا ہے۔ جب اسے کسی دوسری فائل سے import کیا جائے تو اس کی جگہ ایکسٹینشن کے بغیر فائل کا نام 'mymod2' رکھا جاتا ہے۔ چنانچہ براہِ راست چلانے پر mymod2: __main__ اور 直接実行 کی 2 لائنیں پرنٹ ہوتی ہیں، اور import کرنے پر صرف mymod2: mymod2 کی 1 لائن پرنٹ ہوتی ہے۔ if __name__ == '__main__': اسی فرق کو استعمال کر کے "وہ عمل جو صرف اس فائل کو براہِ راست چلانے پر ہونا چاہیے" کو الگ کرنے کا معیاری طریقہ ہے۔ اگر جوڑا الٹ ہوتا تو درست کام کی جانچ کے لیے لکھا گیا کوڈ import کرنے پر بھی چل جاتا، جو اس طریقے کے مقصد کے خلاف ہے۔ اگر دونوں صورتوں میں ایک ہی ویلیو ہوتی تو یہ علیحدگی سرے سے ممکن ہی نہ ہوتی۔
سوال 18 | sys.argv
جب درج ذیل args.py کو python3 args.py foo bar کمانڈ سے چلایا جائے تو ظاہر ہونے والی 2 لائنیں کون سی ہیں؟
sys.argv کمانڈ لائن سے پاس کی گئی ویلیوز کی لسٹ (リスト) ہے، اور اس کے شروع میں خود اسکرپٹ کا نام ہوتا ہے۔ اس مثال میں یہ ['args.py', 'foo', 'bar'] جیسی 3 عناصر کی لسٹ بنتی ہے، اس لیے اس کی len 3 ہے۔ انڈیکس (添字) 1 سے آگے کاٹا گیا sys.argv[1:] اسکرپٹ کے نام کے بغیر ['foo', 'bar'] بنتا ہے۔ اگر آپ سمجھیں کہ پاس کیے گئے آرگیومنٹس کی تعداد ہی لمبائی ہے تو 2 ملے گا، لیکن اس میں شروع کے اسکرپٹ نام کو گننا رہ گیا ہے۔ sys.argv[1:] کو ['args.py', 'foo'] سمجھنا تب ہوتا ہے جب slice کے شروع ہونے کی جگہ غلط سمجھ لی جائے۔ اگر کوئی آرگیومنٹ پاس کیے بغیر چلایا جائے تو لمبائی 1 ہوتی ہے، اور sys.argv[1:] خالی لسٹ ہوتی ہے۔
سوال 19 | ماڈیول کو دوبارہ لوڈ کرنا
ایک ہی پروگرام میں ایک ہی ماڈیول کو دو بار import کرنے پر درست رویہ کون سا ہے؟
دوسری بار ماڈیول کی باڈی شروع سے دوبارہ پڑھی جاتی ہے اور ایک بار پھر چلتی ہے
دوسری بار ایک الگ آبجیکٹ بنتا ہے، اور کوئی حالت (state) شیئر نہیں ہوتی
دوسری بار کیش استعمال ہوتا ہے، اور ماڈیول کی باڈی دوبارہ نہیں چلتی
دوسری بار ImportError آتا ہے، کیونکہ ایک ہی نام ایک سے زیادہ بار استعمال نہیں ہو سکتا
درست جوابC. دوسری بار کیش استعمال ہوتا ہے، اور ماڈیول کی باڈی دوبارہ نہیں چلتی
جو ماڈیول (モジュール) ایک بار import ہو چکا ہو وہ sys.modules نامی ڈکشنری میں کیش (キャッシュ) ہو جاتا ہے۔ دوسرا import صرف نام کو وہاں پہلے سے رجسٹر شدہ اسی ماڈیول آبجیکٹ سے جوڑ دیتا ہے، اس لیے نہ فائل دوبارہ پڑھی جاتی ہے نہ باڈی دوبارہ چلتی ہے۔ آپ ماڈیول کی بالائی سطح پر ایک print رکھ کر اس کی تصدیق کر سکتے ہیں کہ دو بار import کرنے پر بھی وہ صرف ایک بار ظاہر ہوتا ہے۔ اگر کسی دوسرے alias (別名) سے import کیا جائے تب بھی وہ اسی آبجیکٹ کی طرف اشارہ کرتا ہے۔ لہٰذا اگر آپ کسی ماڈیول کا کوئی ویری ایبل بدلیں تو اس ماڈیول کو import کرنے والی ہر دوسری جگہ سے بھی بدلی ہوئی ویلیو نظر آتی ہے۔ ایک ہی نام کو دو بار import کرنے سے ایرر نہیں آتا، اور اگر ڈیولپمنٹ کے دوران باڈی دوبارہ لوڈ کرنی ہو تو importlib کی سہولت واضح طور پر استعمال کرنی ہوگی۔
سوال 20 | ورچوئل انوائرنمنٹ کی جانچ
یہ طے کرنے کا مناسب طریقہ کون سا ہے کہ اس وقت چلنے والا Python، venv سے بنائے گئے ورچوئل انوائرنمنٹ کے اندر ہے یا نہیں؟
اگر sys.prefix متعین نہ ہو تو سمجھا جا سکتا ہے کہ یہ ورچوئل انوائرنمنٹ کے اندر ہے
اگر sys.prefix اور sys.base_prefix ایک جیسے ہوں تو سمجھا جا سکتا ہے کہ یہ ورچوئل انوائرنمنٹ کے اندر ہے
اگر sys.base_prefix متعین ہو تو سمجھا جا سکتا ہے کہ یہ ورچوئل انوائرنمنٹ کے اندر ہے
اگر sys.prefix اور sys.base_prefix مختلف ہوں تو سمجھا جا سکتا ہے کہ یہ ورچوئل انوائرنمنٹ کے اندر ہے
درست جوابD. اگر sys.prefix اور sys.base_prefix مختلف ہوں تو سمجھا جا سکتا ہے کہ یہ ورچوئل انوائرنمنٹ کے اندر ہے
sys.prefix اس جگہ کی نشاندہی کرتا ہے جہاں اس وقت چلنے والا Python انسٹال ہے، اور sys.base_prefix اس اصل Python کی جگہ بتاتا ہے جس سے یہ بنا ہے۔ ورچوئل انوائرنمنٹ (仮想環境) کے باہر دونوں کی ویلیو ایک ہی ہوتی ہے، لیکن python3 -m venv سے بنائے گئے انوائرنمنٹ کے اندر sys.prefix بنائے گئے انوائرنمنٹ کی ڈائریکٹری کی طرف اشارہ کرنے لگتا ہے، جبکہ sys.base_prefix بدستور اصل Python کی طرف اشارہ کرتا رہتا ہے، اس لیے دونوں مختلف ہو جاتے ہیں۔ اسی فرق کا ہونا یا نہ ہونا فیصلے کا اشارہ ہے۔ یہ کہنا کہ ایک جیسا ہونا ورچوئل انوائرنمنٹ کے اندر ہونے کا مطلب ہے، الٹی شرط ہے۔ sys.base_prefix ورچوئل انوائرنمنٹ کے باہر بھی ہمیشہ متعین ہوتا ہے، اس لیے متعین ہونے یا نہ ہونے سے فیصلہ نہیں ہو سکتا۔ sys.prefix بھی ہمیشہ متعین ہوتا ہے۔ مخصوص path کی اسٹرنگز اور pip کا ورژن ہر انوائرنمنٹ میں مختلف ہوتے ہیں، اس لیے صرف یہی تعلق یاد رکھنا کافی ہے۔
سوال 21 | write کی ریٹرن ویلیو
درج ذیل کوڈ ایک write میتھڈ کی ریٹرن ویلیو وصول کرتا ہے۔ کیا ظاہر ہوگا؟
with open('/tmp/sample.txt', 'w') as f:n = f.write("one\ntwo\nthree\n")print(n)
None ظاہر ہوتا ہے
3 ظاہر ہوتا ہے
14 ظاہر ہوتا ہے
11 ظاہر ہوتا ہے
درست جوابC. 14 ظاہر ہوتا ہے
write اپنی ریٹرن ویلیو (戻り値) کے طور پر لکھے گئے کیریکٹرز کی تعداد لوٹاتا ہے۔ "one\ntwo\nthree\n" میں one کے 3 کیریکٹرز، two کے 3 کیریکٹرز اور three کے 5 کیریکٹرز مل کر 11 بنتے ہیں، اور اس کے ساتھ 3 نئی لائن کے کیریکٹرز (改行) لگے ہیں، اس لیے کل 14 کیریکٹرز ہیں۔ نئی لائن کے کیریکٹرز گننا بھول جائیں تو 11 ملتا ہے۔ اگر آپ سمجھیں کہ لکھی گئی لائنوں کی تعداد لوٹتی ہے تو 3 ملے گا، لیکن write صرف کیریکٹرز کی تعداد گنتا ہے۔ یہ فرض کر کے None چننا کہ کچھ واپس نہیں آتا، بھی ایک عام غلطی ہے، اور اسے append یا sort جیسے None لوٹانے والے میتھڈز سے گڈمڈ کرنا آسان ہے، لیکن write ایک تعداد لوٹاتا ہے۔ یہ بھی یاد رکھیں کہ write خود بخود نئی لائن نہیں لگاتا، اس لیے لائنیں الگ کرنی ہوں تو اسے اسٹرنگ میں خود لکھنا ہوگا۔
سوال 22 | readlines
3 لائنوں والی ایک فائل کو readlines سے پڑھا گیا۔ کیا ظاہر ہوگا؟
with open('/tmp/sample.txt', 'w') as f: f.write("one\ntwo\nthree\n")with open('/tmp/sample.txt') as f:print(f.readlines())
['one\ntwo\nthree\n'] ظاہر ہوتا ہے
'one\ntwo\nthree\n' ظاہر ہوتا ہے
['one\n', 'two\n', 'three\n'] ظاہر ہوتا ہے
['one', 'two', 'three'] ظاہر ہوتا ہے
درست جوابC. ['one\n', 'two\n', 'three\n'] ظاہر ہوتا ہے
readlines تمام لائنوں کو ایک لسٹ (リスト) کی شکل میں لوٹاتا ہے، لیکن ہر عنصر کے آخر میں موجود نئی لائن کا کیریکٹر (改行文字) جوں کا توں باقی رہتا ہے۔ اس لیے نتیجہ ['one\n', 'two\n', 'three\n'] ہوتا ہے۔ اگر آپ سمجھیں کہ نئی لائن کے کیریکٹرز ہٹا دیے جاتے ہیں تو ['one', 'two', 'three'] ملے گا، لیکن یہ حاصل کرنے کے لیے ہر عنصر پر rstrip لگانا ہوگا۔ پوری چیز کو تقسیم کیے بغیر ایک اسٹرنگ کے طور پر لوٹانے والا read ہے؛ readlines لسٹ لوٹاتا ہے۔ اگر آپ سمجھیں کہ یہ نئی لائنوں پر تقسیم کیے بغیر پوری فائل کو ایک عنصر کے طور پر لپیٹ دیتا ہے تو ['one\ntwo\nthree\n'] ملے گا، لیکن readlines ہر نئی لائن پر نیا عنصر بناتا ہے۔ جب آپ for line in f لکھ کر ایک ایک لائن نکالتے ہیں تو ملنے والی لائن کے ساتھ بھی اسی طرح نئی لائن کا کیریکٹر لگا ہوتا ہے۔
سوال 23 | دوسری بار read
ایک ہی فائل آبجیکٹ سے لگاتار دو بار پڑھا گیا۔ کیا ظاہر ہوگا؟
with open('/tmp/sample.txt') as f:a = f.read()b = f.read()print(len(a), b == '')
14 False ظاہر ہوتا ہے
14 True ظاہر ہوتا ہے
0 False ظاہر ہوتا ہے
0 True ظاہر ہوتا ہے
درست جوابB. 14 True ظاہر ہوتا ہے
فائل آبجیکٹ (ファイルオブジェクト) اپنی موجودہ پوزیشن یاد رکھتا ہے۔ پہلا read شروع سے آخر تک سب کچھ پڑھ لیتا ہے، اس لیے a میں نئی لائن سمیت 14 کیریکٹرز آتے ہیں، اور پوزیشن آخر پر چلی جاتی ہے۔ دوسرا read آخر سے پڑھنے کی کوشش کرتا ہے، اس لیے کچھ باقی نہیں ہوتا اور خالی اسٹرنگ لوٹتی ہے۔ چنانچہ len(a) 14 ہے، اور b == '' True ہے۔ اگر آپ سمجھیں کہ دوسری بار بھی وہی مواد لوٹتا ہے تو b == '' False ہوگا، لیکن وہی مواد دوبارہ پڑھنے کے لیے f.seek(0) سے پوزیشن کو شروع پر واپس لانا ضروری ہے۔ len(a) کا 0 ہونا تب ہوتا ہے جب فائل خالی ہو، یا پوزیشن پہلے ہی آخر پر ہو۔ کچھ ظاہر نہ ہونے پر اسے پڑھنے میں ناکامی سمجھ لینا آسان ہے، لیکن اصل وجہ یہ ہے کہ پوزیشن آخر پر ہے۔
سوال 24 | with اور close
with بلاک کے اندر اور باہر دونوں جگہ closed کو جانچا گیا۔ ظاہر ہونے والی 2 لائنیں کون سی ہیں؟
with open('/tmp/sample.txt') as f:print(f.closed)print(f.closed)
پہلے False، پھر False
پہلے False، پھر True
پہلے True، پھر False
پہلے True، پھر True
درست جوابB. پہلے False، پھر True
with بلاک کے اندر فائل ابھی کھلی ہوتی ہے، اس لیے closed کی ویلیو False ہے۔ بلاک سے نکلتے وقت یہ خود بخود بند ہو جاتی ہے، اس لیے اس کے بعد closed کی ویلیو True ہو جاتی ہے۔ چنانچہ پہلے False اور پھر True ظاہر ہوتا ہے۔ with استعمال کرنے کا مقصد یہ یقینی بنانا ہے کہ بند کرنے کا یہ عمل لکھنا بھول جانے پر بھی ضرور چلے، اور اگر بلاک کے اندر ایکسیپشن (例外) آئے اور درمیان سے باہر نکلنا پڑے تب بھی فائل بند ہو جاتی ہے۔ کاما سے الگ کر کے ایک ہی with اسٹیٹمنٹ میں کئی فائلیں ایک ساتھ کھولی بھی جا سکتی ہیں، اور ان میں سے ہر ایک اسی طرح بند ہوتی ہے۔ بند ہونے کے بعد فائل آبجیکٹ سے پڑھنے کی کوشش پر ValueError آتا ہے، اس لیے with بلاک کے باہر اسے دوبارہ نہیں پڑھا جا سکتا۔
سوال 25 | لکھنے کا موڈ
ایک ہی فائل کو 3 بار کھول کر اس میں لکھا گیا، اور پھر پڑھا گیا۔ کیا ظاہر ہوگا؟
p = '/tmp/sample.txt'with open(p, 'w') as f: f.write('AAA')with open(p, 'a') as f: f.write('BBB')with open(p, 'w') as f: f.write('C')with open(p) as f:print(f.read())
فائل کا مواد AAABBB ہے
فائل کا مواد AAABBBC ہے
فائل کا مواد C ہے
فائل کا مواد CAABBB ہے
درست جوابC. فائل کا مواد C ہے
'w' سے کھولنے پر فائل اسی لمحے، پہلے سے موجود مواد ہو یا نہ ہو، لمبائی 0 تک کاٹ دی جاتی ہے (切り詰め)۔ ترتیب وار دیکھیں تو پہلا 'w' AAA لکھتا ہے، اور اگلا 'a' اضافہ (追記) ہے، اس لیے مواد AAABBB بنتا ہے۔ لیکن تیسری بار 'w' سے کھولتے ہی AAABBB مٹ جاتا ہے، اور اس میں C لکھا جاتا ہے، اس لیے آخر میں صرف C باقی رہتا ہے۔ اگر آپ سمجھیں کہ تمام 3 بار 'a' سے کھولا گیا تو AAABBBC ملے گا، اور اگر سمجھیں کہ آخری لکھائی نظرانداز ہو گئی تو AAABBB ملے گا۔ کاٹے بغیر شروع سے اوور رائٹ کرنا 'r+' کا رویہ ہے، اور اس صورت میں صرف شروع کا کیریکٹر بدلتا، جیسے CAABBB۔ کٹائی کھولنے کے لمحے ہوتی ہے، لکھنے کے لمحے نہیں، اس لیے 'w' سے کھول کر کچھ بھی نہ لکھا جائے تو فائل خالی رہ جاتی ہے۔ اگر اضافہ کرنا مقصود ہو تو 'a'، اور نئے سرے سے بنانا مقصود ہو تو 'w' استعمال کریں — اپنا ارادہ موڈ کے ذریعے ظاہر کریں۔
سوال 26 | بند کرنے کے بعد کا عمل
اگر بند ہونے کے بعد فائل آبجیکٹ سے پڑھنے کی کوشش کی جائے تو کیا ہوگا؟
f = open('/tmp/sample.txt')f.close()print(f.read())
ValueError آتا ہے، جو بتاتا ہے کہ یہ بند فائل پر عمل ہے
خالی اسٹرنگ ظاہر ہوتی ہے، اور پروگرام معمول کے مطابق ختم ہوتا ہے
فائل خود بخود دوبارہ کھل جاتی ہے، اور اس کا پورا مواد ظاہر ہوتا ہے
OSError آتا ہے، جو بتاتا ہے کہ فائل دوبارہ نہیں کھولی جا سکتی
درست جوابA. ValueError آتا ہے، جو بتاتا ہے کہ یہ بند فائل پر عمل ہے
بند ہو چکے فائل آبجیکٹ (ファイルオブジェクト) پر read کال کرنے سے ValueError آتا ہے، اور I/O operation on closed file والا پیغام دکھائی دیتا ہے۔ چونکہ آبجیکٹ خود یاد رکھتا ہے کہ اسے بند کیا جا چکا ہے، اس لیے صرف ضرورت پڑنے پر یہ خود بخود دوبارہ نہیں کھلتا۔ نہ ہی یہ "پڑھنے کو کچھ نہیں" کے معنی میں خالی اسٹرنگ لوٹاتا ہے — یہ تو آخر تک پڑھ لینے کے بعد والے read کا رویہ ہے۔ فائل نہ ملنے پر آنے والا FileNotFoundError وغیرہ OSError ہی کے خاندان سے ہیں، لیکن بند فائل پر عمل کرنے کا ایکسیپشن (例外) ان سے الگ ہے، اور وہ ValueError ہے۔ with اسٹیٹمنٹ استعمال کرنے سے بلاک سے نکلنے کے بعد پڑھنے کی کوشش والی صورتِ حال ہی ساختی طور پر پیدا نہیں ہوتی۔
سوال 27 | صرف پڑھنے کے لیے
اگر موڈ بتائے بغیر کھولی گئی فائل میں لکھنے کی کوشش کی جائے تو کیا ہوگا؟
with open('/tmp/sample.txt', 'w') as f: f.write('data')with open('/tmp/sample.txt') as f: f.write('more')
io.UnsupportedOperation آتا ہے، جو بتاتا ہے کہ اس میں لکھا نہیں جا سکتا
ValueError آتا ہے، جو بتاتا ہے کہ موڈ کی تعیین غلط ہے
مواد کے آخر میں more جڑ جاتا ہے، اور پروگرام معمول کے مطابق ختم ہوتا ہے
مواد more سے بدل جاتا ہے، اور پروگرام معمول کے مطابق ختم ہوتا ہے
درست جوابA. io.UnsupportedOperation آتا ہے، جو بتاتا ہے کہ اس میں لکھا نہیں جا سکتا
open کا دوسرا آرگیومنٹ چھوڑ دینے سے یہ صرف پڑھنے کے لیے، یعنی 'r'، بن جاتا ہے۔ صرف پڑھنے کے لیے کھولے گئے فائل آبجیکٹ پر write کال کرنے سے io.UnsupportedOperation آتا ہے، اور ساتھ not writable کا پیغام ہوتا ہے۔ چونکہ یہ سنٹیکس کے لحاظ سے درست کوڈ ہے، اس لیے موڈ کی غلطی کا پتا اسے حقیقت میں چلانے پر ہی چلتا ہے۔ اوور رائٹ کرنا ہو تو 'w'، آخر میں اضافہ کرنا ہو تو 'a'، اور پڑھنا لکھنا دونوں ہوں تو 'r+' سے دوبارہ کھولیں۔ اس کے برعکس 'w' یا 'a' سے کھولی گئی فائل پر read کال کرنے سے بھی یہی io.UnsupportedOperation آتا ہے، اس بار not readable کے ساتھ۔ موڈ کو اس طرح سمجھ سکتے ہیں کہ وہ اس فائل آبجیکٹ کے مقام پر اعلان کرتا ہے کہ اس کے ساتھ کیا کرنے کی اجازت ہے۔
سوال 28 | seek اور tell
درج ذیل کوڈ صرف پہلے 5 کیریکٹرز پڑھتا ہے اور پھر پوزیشن جانچتا ہے۔ کیا ظاہر ہوگا؟
with open('/tmp/sample.txt') as f:head = f.read(5)pos = f.tell()f.seek(0)print(repr(head), pos, f.tell())
'one\ntwo\nthree\n' 14 0
'one\nt' 5 0
'one\nt' 5 5
'one\nt' 0 0
درست جوابB. 'one\nt' 5 0
read کو کوئی عدد دیا جائے تو یہ صرف اتنے ہی کیریکٹرز پڑھتا ہے۔ پہلے 5 کیریکٹرز میں one کے 3 کیریکٹرز، 1 نئی لائن کا کیریکٹر (改行)، اور two کا t شامل ہیں، یعنی 'one\nt'۔ جتنا پڑھا جائے پوزیشن اتنی آگے بڑھتی ہے، اس لیے فوراً بعد والا tell 5 لوٹاتا ہے۔ اس کے بعد seek(0) پوزیشن کو شروع پر واپس لے آتا ہے، اس لیے آخری tell 0 ہے۔ اگر آپ سمجھیں کہ read پوزیشن نہیں ہلاتا تو tell دونوں بار 0 لوٹائے گا، اور اگر سمجھیں کہ seek کا کوئی اثر نہیں تو tell دونوں بار 5 لوٹائے گا۔ اگر read کے آرگیومنٹ کو کیریکٹرز کی تعداد کے بجائے لائنوں کی تعداد سمجھ لیا جائے اور لائن 5 تک پڑھنے کا ارادہ ہو تو غلطی سے پوری فائل 'one\ntwo\nthree\n' اور 14 چن لیا جائے گا۔ seek(0) استعمال کر کے اسی فائل آبجیکٹ پر شروع سے دوبارہ پڑھا جا سکتا ہے۔
سوال 29 | JSON اور ٹیوپلز
درج ذیل کوڈ ٹیوپل والی ایک ڈکشنری کو JSON میں بدل کر واپس پڑھتا ہے۔ ظاہر ہونے والی 2 لائنیں کون سی ہیں؟
درست جوابD. پہلے {"t": [1, 2]}، پھر {'t': [1, 2]} list
JSON میں صرف arrays (配列) ہوتے ہیں؛ ٹیوپل (タプル) نام کی کوئی ٹائپ نہیں۔ اس لیے dumps کے وقت ٹیوپل array میں بدل جاتا ہے، اور آؤٹ پٹ {"t": [1, 2]} ہوتا ہے۔ واپس پڑھتے وقت array لسٹ کی شکل میں بحال ہوتا ہے، اس لیے back['t'] کی ٹائپ list ہے؛ یہ ٹیوپل میں واپس نہیں جاتا۔ یہ معلومات کہ اصل میں یہ ٹیوپل تھا، کہیں محفوظ نہیں رہتی، اس لیے آنے جانے کے دوران ٹائپ بدل جاتی ہے۔ اگر اسے ٹیوپل ہی رکھنا ہو تو واپس پڑھنے کے بعد ویلیو پر خود tuple() لگانا ہوگا۔ JSON آؤٹ پٹ میں گول بریکٹس کبھی ظاہر نہیں ہوتے، اور ٹیوپل اسٹرنگ میں بھی نہیں بدلتا۔ اسی وجہ سے، ڈکشنری کی key کے طور پر انٹیجر استعمال کیا جائے تو dumps اسے اسٹرنگ میں بدل دیتا ہے، اور واپس پڑھنے پر بھی یہ انٹیجر میں واپس نہیں جاتا۔
سوال 30 | JSON کی keys
اگر انٹیجر key والی ایک ڈکشنری اور ایک سیٹ کو JSON میں بدلنے کی کوشش کی جائے تو کیا ہوگا؟
لائن 1 پر {1: "a"} اور لائن 2 پر [1, 2] ظاہر ہوتا ہے
لائن 1 پر TypeError آتا ہے، اور لائن 2 نہیں چلتی
لائن 1 پر {"1": "a"} ظاہر ہوتا ہے، اور لائن 2 پر TypeError آتا ہے
لائن 1 پر {"1": "a"} اور لائن 2 پر [1, 2] ظاہر ہوتا ہے
درست جوابC. لائن 1 پر {"1": "a"} ظاہر ہوتا ہے، اور لائن 2 پر TypeError آتا ہے
JSON آبجیکٹ کی keys کا اسٹرنگ ہونا لازمی ہے، اس لیے انٹیجر key والی ڈکشنری (辞書) پر dumps کال کرنے سے key اسٹرنگ میں بدل جاتی ہے، اور آؤٹ پٹ {"1": "a"} ہوتا ہے۔ یہ عمل معمول کے مطابق کامیاب ہوتا ہے؛ یہاں کوئی ایکسیپشن نہیں آتا۔ البتہ یاد رکھیں کہ واپس پڑھنے پر key اسٹرنگ ہی رہتی ہے اور انٹیجر میں واپس نہیں جاتی۔ دوسری لائن کے سیٹ (集合) کی JSON میں کوئی متعلقہ ٹائپ نہیں، اس لیے اس پر dumps کال کرنے کی کوشش سے TypeError آتا ہے، اور Object of type set is not JSON serializable کا پیغام ملتا ہے۔ اگر آپ سمجھیں کہ سیٹ array کی شکل میں لکھا جائے گا تو [1, 2] ملے گا، لیکن اگر یہ تبدیلی چاہیے تو پاس کرنے سے پہلے اس پر خود list() لگانا ہوگا۔ جاپانی متن والی ویلیوز ڈیفالٹ طور پر آؤٹ پٹ میں escape ہو جاتی ہیں، اور ensure_ascii کو false (غلط) دینے سے وہ اصل کیریکٹرز کی شکل میں آؤٹ پٹ ہوتی ہیں۔
مشق: اس صفحے کے سوالات حل کریں
یہ بے ترتیب سوالات والا مشق کا ٹول ہے (JavaScript فعال ہونے پر کام کرتا ہے)۔ اوپر دیے گئے تمام سوالات اور وضاحتیں اس کے بغیر بھی پڑھی جا سکتی ہیں۔
※ وضاحتیں مطالعے کے مقصد کے لیے معلومات ہیں۔ امتحان کا نصاب اور نظام سال بہ سال بدل سکتا ہے، اس لیے امتحان منعقد کرنے والے ادارے کے سرکاری اعلانات ضرور دیکھیں۔
یہ صفحہ جاپانی اصل متن کا ترجمہ ہے۔ اگر ترجمے اور اصل متن میں فرق ہو تو جاپانی ورژن کو ترجیح دی جائے گی۔ یہ ترجمہ AI کی مدد سے کیا گیا ہے اور اس میں غلطیاں ہو سکتی ہیں۔ترجمے کی غلطی کی اطلاع دیںجاپانی اصل متن دیکھیں