Python: المنطق البولياني
في الدرس 03، تعلمنا عن المعاملات، بما في ذلك المعاملات المنطقية
andوorوnot. في هذا الدرس، سنركز على أحكام الصواب/الخطأ — المفهوم الأكثر أساسية في علوم الحاسوب. المنطق البولياني هو أساس جميع الجمل الشرطية، وتحكم الحلقات، وفحوصات الأذونات.
1. القيم البوليانية: True و False
هناك قيمتان بوليانتان فقط: True و False. سُميتا على اسم عالم الرياضيات البريطاني جورج بول، الذي أسس الجبر البولياني — الأساس النظري لـ "0 و 1" في الحوسبة الحديثة.
print(True) # الناتج: True
print(False) # الناتج: False
print(type(True)) # <class 'bool'>
تنتج معاملات المقارنة نتائج بوليانية:
print(5 > 3) # True
print(10 == 5) # False
print(7 <= 7) # True
print(3 != 3) # False
(1) القيم البوليانية هي أرقام أيضاً
في بايثون، True و False هما في الواقع فئتان فرعيتان من int — True يكافئ 1، و False يكافئ 0:
print(True + True) # 2 (True=1، و True مرتان = 2)
print(True * 10) # 10
print(False * 100) # 0
تحذير: رغم أن
True == 1وFalse == 0صحيحتان في بايثون (لذاTrue + Trueيساوي 2)، لا تستخدمهما بهذه الطريقة أبداً. القيم البوليانية مخصصة للحكم المنطقي، وليس للحساب. كتابة كود مثلscore + Trueستسبب ارتباكاً للقراء.
▶ مثال: نتائج فحص الصحة (الصعوبة ⭐)
# توليد قيم بوليانية باستخدام معاملات المقارنة
age = 25
height = 175
weight = 70
is_adult = age >= 18 # True
is_tall = height > 170 # True
is_heavy = weight > 80 # False
print(f"Adult: {is_adult}")
print(f"Tall: {is_tall}")
print(f"Overweight: {is_heavy}")
# إخراج القيم البوليانية مباشرة — إنها قيم وليست نصاً
print(f"Adult AND Tall: {is_adult and is_tall}")
Output:
Adult: True
Tall: True
Overweight: False
Adult AND Tall: True
2. not: النفي
not تعني "العكس" — الأسود يصبح أبيض، والأبيض يصبح أسود.
print(not True) # False
print(not False) # True
print(not (5 > 3)) # False (5>3 صحيحة، وبالنفي تصبح False)
تُستخدم not عادة في سيناريوهين:
السيناريو 1: التحقق من "عدم تحقق شرط"
# ليس مديراً — لا يمكنه الدخول إلى الواجهة الخلفية
is_admin = False
if not is_admin:
print("You do not have admin access.")
# الناتج: You do not have admin access.
السيناريو 2: التحقق مما إذا كان المتغير فارغاً
# تحقق مما إذا كان المستخدم لم يقدم اسماً
username = ""
if not username:
print("Username cannot be empty!")
# الناتج: Username cannot be empty!
هناك حيلة "التحويل البولياني الضمني" في بايثون هنا — السلسلة الفارغة "" تعادل False في فحوصات الشرط. لذلك not username تكون True عندما يكون username سلسلة فارغة. سنتناول القيم "الزائفة" لاحقاً.
تلميح:
notتعني "النفي". في الكود، تُقرأif not is_admin:على أنها "إذا لم يكن مديراً".
3. and: يجب أن يكون كلاهما True
and تعني "كلاهما" — يجب أن يكون كلا الشرطين صحيحين ليكون الناتج True. إذا كان أي منهما خاطئاً، يكون الناتج False.
| اليسار | اليمين | النتيجة |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
age = 22
has_id = True
# يجب تحقق كلا الشرطين
can_buy_alcohol = age >= 18 and has_id
print(can_buy_alcohol) # True (بالغ ويحمل بطاقة هوية)
# سيناريو آخر: طلب بطاقة ائتمان يتطلب دخلاً >= 50 ألفاً ودرجة ائتمان >= 600
income = 80 # بالآلاف
credit_score = 650
qualified = income >= 50 and credit_score >= 600
print(f"Credit card application: {qualified}") # True
▶ مثال: فحص تسجيل الدخول (الصعوبة ⭐)
# محاكاة تسجيل الدخول — اسم مستخدم صحيح وكلمة مرور صحيحة
username_correct = True
password_correct = False
can_login = username_correct and password_correct
print(f"Login result: {can_login}") # False — كلمة المرور خاطئة
# أضف طبقة أخرى: يجب ألا يكون الحساب مقفلاً
account_locked = True
can_login = username_correct and password_correct and not account_locked
print(f"Final result: {can_login}") # False — الحساب مقفل
Output:
Login result: False
Final result: False
4. or: واحد على الأقل True
or تعني "أيهما" — إذا كان شرط واحد على الأقل صحيحاً، يكون الناتج True. فقط عندما يكون كلاهما خاطئاً يكون الناتج False.
| اليسار | اليمين | النتيجة |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
# يمكن الراحة في عطلات نهاية الأسبوع أو الإجازات
is_weekend = True
is_holiday = False
can_rest = is_weekend or is_holiday
print(can_rest) # True (إنها عطلة نهاية الأسبوع)
# أمن المترو: إذا كان لديك ماء أو مشروب، تحتاج إلى فحص
has_water = True
has_drink = False
need_check = has_water or has_drink
print(f"Security check needed: {need_check}") # True
(1) تمرين: التحقق الكامل من جدول الحقيقة
# تحقق من جدول الحقيقة بالكود — كل تركيبات and و or
a = True
b = True
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = True
b = False
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = False
b = True
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = False
b = False
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
Output:
True and True = True
True or True = True
True and False = False
True or False = True
False and True = False
False or True = True
False and False = False
False or False = False
5. التقييم بالدائرة القصيرة
ذكرنا هذا في الدرس 03، لكنه مهم جداً لدرجة أننا سنتعمق أكثر. المعاملات المنطقية في بايثون تتوقف عن التقييم فوراً بمجرد تحديد النتيجة، دون تنفيذ بقية التعبير.
(1) الدائرة القصيرة لـ and: اليسار False -> اليمين لا يُنفذ
def check_right():
print("-> check_right was called!")
return True
print("False and check_right():")
result = False and check_right() # check_right لن تُنفذ
print(f"Result: {result}\n")
print("True and check_right():")
result = True and check_right() # check_right ستُنفذ
print(f"Result: {result}")
Output:
False and check_right():
Result: False
True and check_right():
-> check_right was called!
Result: True
(2) الدائرة القصيرة لـ or: اليسار True -> اليمين لا يُنفذ
print("True or check_right():")
result = True or check_right() # check_right لن تُنفذ
print(f"Result: {result}")
(3) الاستخدامات الكلاسيكية للتقييم بالدائرة القصيرة
1. الوصول الآمن: منع أخطاء None
# افترض أن user قد يكون None (المستخدم غير موجود)
user = None
# user.get("name") سيسبب خطأً — None ليس له طريقة get
# استخدم الدائرة القصيرة للحماية:
name = user and user.get("name")
print(name) # None — user زائف، حدثت دائرة قصيرة، ولم تُستدعَ user.get()
# إذا كان المستخدم موجوداً:
user = {"name": "Xiao Ming"}
name = user and user.get("name")
print(name) # Xiao Ming
2. تعيين القيم الافتراضية
# إذا لم يُدخل المستخدم اسماً، استخدم قيمة افتراضية
user_input = "" # سلسلة فارغة (زائفة)
name = user_input or "guest"
print(f"Welcome, {name}") # Welcome, guest
user_input = "Zhang San"
name = user_input or "guest"
print(f"Welcome, {name}") # Welcome, Zhang San
تلميح: النمط
user_input or "default"بيثوني جداً — إذا كان الجانب الأيسر زائفاً (سلسلة فارغة)، استخدم الأيمن؛ وإذا كان صادقاً (به محتوى)، استخدم الأيسر. إنه يستفيد من سلوك الدائرة القصيرة لـor.
6. القيم الصادقة والزائفة
في بايثون، يمكن استخدام أي قيمة كقيمة بوليانية في الشرط. بعض القيم تعتبر "زائفة"، وكل ما عداها "صادق".
(1) القيم الزائفة الشائعة
# هذه القيم تعادل False في الشروط
print(bool(False)) # False — بولياني خاطئ
print(bool(0)) # False — صفر
print(bool(0.0)) # False — صفر عشري
print(bool("")) # False — سلسلة فارغة
print(bool([])) # False — قائمة فارغة (سنغطيها لاحقاً)
print(bool(None)) # False — قيمة فارغة
كل ما عدا ذلك صادق:
print(bool(1)) # True — عدد غير صفري
print(bool(-5)) # True — الأعداد السالبة صادقة أيضاً!
print(bool("Python")) # True — سلسلة غير فارغة
print(bool(" ")) # True — المسافة حرف، وغير الفارغ صادق
print(bool([1, 2])) # True — قائمة غير فارغة
تحذير:
-5و" "(المسافة) كلاهما صادق، وقد يفاجئك ذلك.-5عدد صحيح غير صفري، لذا فهو صادق. المسافة حرف، مما يجعل السلسلة غير فارغة، لذا فهي صادقة. فقط السلسلة الفارغة""زائفة.
(2) استخدام الصدقية لتبسيط الكود
# غير موصى به (مطوّل)
name = "Xiao Ming"
if name != "":
print(f"Hello, {name}")
# موصى به (موجز)
name = "Xiao Ming"
if name:
print(f"Hello, {name}")
# غير موصى به
score = 85
if score != 0:
print(f"Score: {score}")
# موصى به
score = 85
if score:
print(f"Score: {score}")
تلميح: الاستفادة من الصدقية تجعل الكود أنظف.
if name:أكثر "بيثونية" منif name != "":. لكن احذر من المبالغة —if score:لن تُنفذ عندما يكونscore=0. إذا كنت بحاجة للتمييز بين "الدرجة 0" و "لا توجد درجة"، استخدمis not None.
7. is و is not: مقارنة الهوية
is تقارن ما إذا كان المتغيران يشيران إلى نفس الكائن (نفس المساحة في الذاكرة)، وليس ما إذا كانت قيمهما متساوية. ذكرنا هذا في الدرس 03؛ إليك المزيد من الأمثلة للترسيخ.
# == تقارن القيم، is تقارن الهوية
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True — نفس القيم
print(a is b) # False — لكنهما ليسا نفس كائن القائمة
print(a is c) # True — c هي a، تشير إلى نفس القائمة
# تخزين الأعداد الصحيحة الصغيرة مؤقتاً (تحسين داخلي في بايثون)
x = 256
y = 256
print(x is y) # قد تكون True — الأعداد الصحيحة الصغيرة تُخزن مؤقتاً
x = 1000
y = 1000
print(x is y) # قد تكون False — الأعداد الصحيحة الكبيرة لا تُخزن مؤقتاً
تحذير: لا تستخدم
isأبداً لمقارنة الأعداد الصحيحة أو السلاسل بالقيمة. رغم أن الأعداد الصحيحة الصغيرة قد تعيدTrueأحياناً معisبسبب التحسين الداخلي في بايثون، فإن هذا تفصيل تنفيذي وغير موثوق. استخدم دائماً==لمقارنة القيم.
(1) الاستخدام الصحيح: التحقق من None
لدى مجتمع بايثون عرف — عند التحقق مما إذا كانت القيمة None، استخدم دائماً is، وليس == أبداً:
# الطريقة الصحيحة
result = None
if result is None:
print("No result")
# غير موصى به
if result == None:
print("No result")
▶ مثال: التحقق من شروط التسجيل (الصعوبة ⭐⭐)
username = "alice2026"
password = "abc123"
age = 20
agreed_terms = True
is_valid = (
bool(username) and
len(password) >= 6 and
age >= 18 and
agreed_terms
)
reason = (
(not username and "Username is empty") or
(len(password) < 6 and "Password too short") or
(age < 18 and "Underage") or
(not agreed_terms and "Terms not agreed") or
"Registration successful"
)
print(f"Registration result: {is_valid}")
print(f"Reason: {reason}")
age = 16
is_valid2 = bool(username) and len(password) >= 6 and age >= 18 and agreed_terms
reason2 = (
(not username and "Username is empty") or
(len(password) < 6 and "Password too short") or
(age < 18 and "Underage") or
(not agreed_terms and "Terms not agreed") or
"Registration successful"
)
print(f"Registration result: {is_valid2}")
print(f"Reason: {reason2}")
Output:
Registration result: True
Reason: Registration successful
Registration result: False
Reason: Underage
8. حالات الاستخدام الشائعة
- التحكم في الأذونات:
is_admin or (is_logged_in and has_permission)— اجمع شروطاً متعددة لتقرير ما يمكن للمستخدم فعله. - التحقق من المدخلات:
username and password— تحقق مما إذا كان المستخدم قد قدم كلاهما. - القيم الافتراضية للمعاملات الاختيارية:
timeout or 30— إذا لم يُضبط المهلة، استخدم القيمة الافتراضية 30 ثانية. - سلسلة الوصول الآمن:
user and user.address and user.address.city— وصول آمن طبقة بطبقة؛ دائرة قصيرة عند أي خطوة زائفة. - التحكم بالتبديل:
is_enabled and is_connected— يجب تحقق كلا الشرطين لتتابع العملية.
❓ أسئلة شائعة
True و "True"؟True (بدون علامات اقتباس) قيمة بوليانية؛ و "True" (بعلامات اقتباس) سلسلة نصية. إنهما مختلفتان: type(True) هي <class 'bool'>، و type("True") هي <class 'str'>. في الشرط، if "True": دائماً True (السلسلة غير الفارغة صادقة)، و if "False": أيضاً دائماً True (غير فارغة أيضاً). لذا لا تضع علامات اقتباس حول القيم البوليانية في الشروط أبداً.is مقابل ==؟== في 99% من الحالات. is عرفية فقط في سيناريو واحد — التحقق من None: if result is None:. استخدم == لكل مقارنات القيم الأخرى. تذكر: == تقارن "القيمة"، و is تقارن "الهوية".and/or؟and أو or، فقد لا يُنفذ بسبب الدائرة القصيرة، ولن تعرف أنه تم تخطيه. إذا كانت تلك الدالة لها آثار جانبية (تسجيل السجلات، إرسال رسائل البريد الإلكتروني، تحديث العدادات)، فقد تسبب الدائرة القصيرة سلوكاً غير متسق. ممارسة جيدة: إذا كان للتعبير الأيمن آثار جانبية، لا تعتمد على الدائرة القصيرة — اكتبها بشكل منفصل.not not "hello" قيمة True؟not "hello" تقيّم أولاً "hello" كقيمة بوليانية (السلسلة غير الفارغة صادقة)، ثم تنفيها لتحصل على False. ثم not not "hello" تنفي False مرة أخرى، لتحصل على True. لذا not not x تعادل bool(x) — تحويل x إلى قيمة بوليانية. لكن هذا النمط غير شائع؛ استخدم bool(x) مباشرة للوضوح.📖 ملخص
- القيم البوليانية لها قيمتان فقط:
TrueوFalse؛ وهما فئتان فرعيتان منint(True=1،False=0)، لكن لا تستخدمهما في الحساب notتنفي: الصواب يصبح خطأ، والخطأ يصبح صواباًandتتطلب أن يكون كلاهما صحيحاًorتتطلب أن يكون واحد على الأقل صحيحاً- القيم الزائفة في بايثون تشمل:
False،0،0.0،""،[]،None— كل ما عداها صادق - الدائرة القصيرة:
andمع يسار خاطئ -> اليمين لا يُنفذ؛orمع يسار صحيح -> اليمين لا يُنفذ - تتيح الدائرة القصيرة نمطين كلاسيكيين: "الوصول الآمن" و "القيم الافتراضية"
isتقارن الهوية، و==تقارن القيمة؛ استخدمisلفحوصاتNone
📝 تمارين
-
مبتدئ (الصعوبة ⭐): توقع قيم هذه التعبيرات، ثم تحقق منها:
not (10 > 5)True and False or Truenot False and True(5 > 3) or (2 > 10) and (8 == 8)— تلميح: انتبه للأسبقية —andأعلى منor
-
متوسط (الصعوبة ⭐⭐): اكتب كوداً للتحقق من سلسلة إدخال المستخدم:
- إذا كان الإدخال فارغاً، أخرج "Input cannot be empty"
- إذا كان الإدخال مسافات فقط، عامله أيضاً كـ "Input cannot be empty" (تلميح: استخدم
strip()) - إذا كان طول الإدخال أقل من 6، أخرج "Input must be at least 6 characters"
- وإلا، أخرج "Input is valid"
-
متقدم (الصعوبة ⭐⭐⭐): اكتب "مدقق أرقام من ثلاثة خانات". بالنظر إلى رقم من 3 خانات
num(مثل 153)، حدد:- هل هو زوجي؟ (استخدم
%) - هل يقبل القسمة على 3 و 5 معاً؟
- هل هو متناظر (palindrome)؟ (رقم المئات يساوي رقم الآحاد، مثل 121، 353)
- كم عدد الشروط المذكورة أعلاه المتحققة؟ أخرج العدد.
استخدم التعبيرات البوليانية فقط لكل الفحوصات — بدون جمل if (احتفظ بذلك للدرس القادم).
- هل هو زوجي؟ (استخدم