نوعان من الأعداد، وقيمة منطقية واحدة
في بايثون، أكثر الأنواع الرقمية استخدامًا في العمل اليومي هما int و float، بالإضافة إلى bool للتعبير عن الصواب والخطأ. هذه الأنواع الثلاثة تغطي تقريبًا كل ما تحتاجه من عمليات حسابية ومنطقية في أي برنامج بايثون عادي.
في بعض الأحيان تُعامل بايثون القيم المنطقية باعتبارها نوعًا فرعيًا من الأعداد الصحيحة، فـ True هي حرفيًا 1 و False هي حرفيًا 0، وهذه الخاصية تفتح لنا الباب أمام حيل مفيدة سنراها لاحقًا.
العمليات الحسابية على الأعداد الصحيحة
الأعداد الصحيحة في بايثون لا تتجاوز حدًا معينًا أبدًا (no overflow). قد تظن أن هذا تفصيل لا يستحق الذكر، لكن بمجرد أن تكتب أول دالة لحساب المضروب (factorial) ستدرك قيمته، إذ إن معظم اللغات الأخرى كانت ستنقلب بصمت إلى رقم سالب عند هذه النقطة.
كلا النوعين يعطيك نتائج دقيقة تمامًا مهما كبر حجم الرقم، والحد الوحيد هنا هو الذاكرة المتاحة.
أما العمليات الحسابية في بايثون فهي مألوفة كما تتوقع، مع إضافة عمليتين مميزتين:
ثلاث نقاط تستحق أن تحفظها من القائمة السابقة:
- العامل
/يُرجِع دائمًا قيمة من نوع float في Python 3، حتى لو كان الطرفان عددين صحيحين. فمثلًا10 / 2يعطيك5.0وليس5. وإذا أردت الحصول على عدد صحيح، استخدم//. - العامل
//يُقرِّب باتجاه اللانهاية السالبة، لذلك-7 // 2يساوي-4وليس-3. قد يبدو الأمر غريبًا، لكنه سلوك منطقي ومتّسق. - العامل
%يُعطي باقي القسمة، وهو مفيد جدًا لمعرفة ما إذا كان العدد زوجيًا (n % 2 == 0) أو للدوران داخل مدى ثابت.
الأعداد العشرية ومشكلتها الشهيرة
الأعداد العشرية (float) غير دقيقة بطبيعتها. فهي تُخزَّن في النظام الثنائي، وهذا النظام لا يستطيع تمثيل أغلب الكسور العشرية بدقة تامة. والمثال الكلاسيكي على ذلك:
السطر الأول يطبع 0.30000000000000004، والثاني يطبع False. كل لغة تتبع معيار IEEE 754 — بايثون وجافاسكريبت وجافا وC — تتصرف بنفس الطريقة. هذا ليس خطأً في بايثون.
من الناحية العملية، هذا يعني أمرين:
- لا تقارن الأعداد العشرية باستخدام
==. إذا احتجت إلى مقارنة "تقريبية"، استخدمmath.isclose(a, b)أو تحقق مما إذا كانabs(a - b) < some_tolerance. - للتعامل مع المبالغ المالية، استخدم
decimal.Decimal. توفر وحدةdecimalفي المكتبة القياسية حسابات عشرية دقيقة تمامًا — بلا مفاجآت مثل0.1 + 0.2. هي أبطأ منfloat، ولهذا ليست الخيار الافتراضي، لكنها الخيار الصحيح عند التعامل مع العملات.
التحويل بين أنواع الأعداد في بايثون
بايثون لا تحوّل الأعداد إلى نصوص أو النصوص إلى أعداد من تلقاء نفسها، بل عليك أن تطلب ذلك صراحةً:
التحويلات غير الصالحة بترفع ValueError:
>>> int("hello")
ValueError: invalid literal for int() with base 10: 'hello'
رسالة الخطأ واضحة وصريحة، وتخبرك مباشرةً بما يجب فعله: إمّا أن تُنظّف المدخلات قبل التحويل، أو تلتقط الاستثناء وتتعامل معه.
القيم المنطقية في بايثون عن قرب
True و False هما القيمتان المنطقيتان الوحيدتان في بايثون من نوع bool، وتُكتبان هكذا تمامًا مع حرف أوّل كبير. ومعظم عمليات المقارنة التي تُجريها تُعيد إحدى هاتين القيمتين:
المعاملات المنطقية في بايثون هي and و or و not، وتُكتب ككلمات إنجليزية بدلاً من الرموز:
تفصيلة مفيدة يجدر الانتباه لها: عاملا and و or لا يُرجعان بالضرورة True أو False، بل يُرجعان القيمة التي حسمت التعبير. مثلاً 0 or "fallback" يُرجع "fallback"، و 5 and 10 يُرجع 10. هذا السلوك مفيد لكتابة قيم افتراضية مختصرة مثل name = user_input or "anonymous"، ومهم أيضاً أن تفهمه حتى لا تتفاجأ إذا أعاد لك فحص منطقي نوعاً غير متوقع.
القيم الصادقة والكاذبة (Truthy و Falsy) في بايثون
تتعامل بايثون مع كثير من القيم على أنها "شبه صادقة" أو "شبه كاذبة" عند استخدامها في سياق منطقي مثل if أو while. القيم الكاذبة (falsy) هي:
False0و0.0None- الحاويات الفارغة:
""و[]و{}وset()و()
وما عدا ذلك يُعتبر صادقاً (truthy). هذا يتيح لك كتابة فحوصات تبدو أكثر طبيعية:
اقرأ if name: وكأنك تقول "إذا كان name فيه شيء". هذا أنظف بكثير من if name != "":. لكن خُذ حذرك مع الأرقام — if count: سيعامل 0 على أنه "تجاوز"، وهذا في الغالب ما تريده، لكن ليس دائمًا. إذا كان الصفر قيمة مشروعة فعلًا، استخدم if count is not None: بدلًا من ذلك.
الحساب بالقيم المنطقية
بما أن القيم المنطقية هي أعداد صحيحة في الأساس، يمكنك إجراء عمليات حسابية عليها مباشرة:
هذه الحيلة تتكرر كثيراً ويستحق الأمر حفظها. لو أردت معرفة عدد العناصر في قائمة معيّنة التي تحقق شرطاً ما، فاجمع مولِّداً (generator) يُرجع قيماً منطقية:
خلاصة عملية تستاهل تتذكرها
- الأعداد الصحيحة
intفي بايثون ما تفيض أبدًا، فاستخدمها براحتك. - العامل
/يرجّعfloatدائمًا، أما إذا بدك قسمة صحيحة استعمل//. - لا تقارن الأعداد العشرية بـ
==، قارنها ضمن هامش خطأ صغير، أو استخدمDecimalلما تتعامل مع أموال. - مفهوم truthy و falsy يخلي شروطك أوضح وأقصر، بس خلّي ببالك إنّ
0والسلاسل الفارغة تُعتبر falsy.
في الدرس القادم: input و print، الأداتان اللي تحوّل سكربتاتك من برامج صامتة إلى محادثة حقيقية مع المستخدم.
الأسئلة الشائعة
ما الفرق بين int و float في بايثون؟
النوع int هو عدد صحيح بدون فاصلة عشرية، بينما float عدد يحتوي على فاصلة عشرية. الأعداد الصحيحة في بايثون يمكن أن تكون بأي حجم — لا يوجد overflow إطلاقًا. أما الأعداد العشرية فتتبع معيار IEEE 754، وهذا يعني أنها قد تفقد جزءًا بسيطًا من الدقة عند إجراء العمليات الحسابية على الكسور العشرية.
لماذا لا يساوي 0.1 + 0.2 القيمة 0.3 في بايثون؟
السبب أن الأعداد العشرية في النظام الثنائي لا يمكنها تمثيل معظم الكسور العشرية بدقة تامة. فالعملية 0.1 + 0.2 تعطي 0.30000000000000004. هذا ليس خطأً في بايثون — أي لغة تستخدم معيار IEEE 754 ستعطي نفس النتيجة. إذا احتجت إلى دقة عشرية كاملة، استخدم وحدة decimal.
ما هي قيم truthy و falsy في بايثون؟
تتعامل بايثون مع الكثير من القيم على أنها صحيحة أو خاطئة في السياقات المنطقية، حتى لو لم تكن True أو False حرفيًا. فالصفر، والسلاسل النصية الفارغة، والقوائم الفارغة، والقواميس الفارغة، وNone كلها falsy، أما معظم القيم الأخرى فهي truthy. لذلك تقرأ الجملة if my_list: كأنها تقول: "إذا كانت القائمة تحتوي على أي عنصر".