Python Logical Operators: and, or, not - Complete Guide

Master Python's logical operators (and, or, not) with practical examples, truth tables, and real-world applications for better conditional logic.

Logical Operators in Python

Introduction

Logical operators in Python are fundamental tools used to combine conditional statements and perform boolean operations. These operators allow developers to create complex decision-making structures by evaluating multiple conditions simultaneously. Python provides three primary logical operators: and, or, and not. Understanding these operators is crucial for writing effective conditional statements, loops, and complex program logic.

Overview of Logical Operators

Logical operators work with boolean values (True and False) and return boolean results. They follow the principles of boolean algebra and are essential for controlling program flow, data validation, and implementing complex business logic.

The Three Primary Logical Operators

1. The and Operator

The and operator returns True only when both operands are True. If either operand is False, the entire expression evaluates to False.

Syntax: `python result = condition1 and condition2 `

Truth Table for and Operator:

| Operand 1 | Operand 2 | Result | |-----------|-----------|--------| | True | True | True | | True | False | False | | False | True | False | | False | False | False |

Basic Examples:

`python

Simple boolean values

print(True and True) # Output: True print(True and False) # Output: False print(False and True) # Output: False print(False and False) # Output: False

Using variables

a = 5 b = 10 result = (a > 0) and (b > 5) print(result) # Output: True

Multiple conditions

age = 25 salary = 50000 experience = 3 eligible = (age >= 18) and (salary > 30000) and (experience >= 2) print(eligible) # Output: True `

Advanced Examples:

`python

Using and with different data types

def validate_user_input(username, password, email): return (len(username) >= 3) and (len(password) >= 8) and ("@" in email)

Example usage

user_valid = validate_user_input("john_doe", "password123", "john@example.com") print(f"User input valid: {user_valid}") # Output: User input valid: True

Chaining multiple and operations

def check_grade_eligibility(math_score, science_score, english_score, attendance): return (math_score >= 70) and (science_score >= 70) and (english_score >= 70) and (attendance >= 85)

student_eligible = check_grade_eligibility(75, 80, 72, 90) print(f"Student eligible: {student_eligible}") # Output: Student eligible: True `

2. The or Operator

The or operator returns True if at least one of the operands is True. It returns False only when both operands are False.

Syntax: `python result = condition1 or condition2 `

Truth Table for or Operator:

| Operand 1 | Operand 2 | Result | |-----------|-----------|--------| | True | True | True | | True | False | True | | False | True | True | | False | False | False |

Basic Examples:

`python

Simple boolean values

print(True or True) # Output: True print(True or False) # Output: True print(False or True) # Output: True print(False or False) # Output: False

Using variables

temperature = 35 humidity = 60 comfortable = (temperature < 30) or (humidity < 50) print(comfortable) # Output: False (both conditions are false)

Access control example

is_admin = False is_moderator = True has_access = is_admin or is_moderator print(has_access) # Output: True `

Advanced Examples:

`python

Multiple or conditions

def check_payment_method(cash, credit_card, debit_card, digital_wallet): return cash or credit_card or debit_card or digital_wallet

payment_available = check_payment_method(False, True, False, False) print(f"Payment method available: {payment_available}") # Output: Payment method available: True

Combining with functions

def is_weekend(day): return day.lower() == "saturday" or day.lower() == "sunday"

def is_holiday(date): holidays = ["2024-01-01", "2024-07-04", "2024-12-25"] return date in holidays

def is_day_off(day, date): return is_weekend(day) or is_holiday(date)

day_off = is_day_off("Saturday", "2024-06-15") print(f"Is day off: {day_off}") # Output: Is day off: True `

3. The not Operator

The not operator is a unary operator that reverses the boolean value of its operand. It returns True if the operand is False, and False if the operand is True.

Syntax: `python result = not condition `

Truth Table for not Operator:

| Operand | Result | |---------|--------| | True | False | | False | True |

Basic Examples:

`python

Simple boolean values

print(not True) # Output: False print(not False) # Output: True

Using with variables

is_logged_in = False show_login_form = not is_logged_in print(show_login_form) # Output: True

Negating conditions

age = 16 is_adult = age >= 18 is_minor = not is_adult print(f"Is minor: {is_minor}") # Output: Is minor: True `

Advanced Examples:

`python

Using not with complex expressions

def is_valid_password(password): return len(password) >= 8 and any(c.isdigit() for c in password) and any(c.isalpha() for c in password)

def password_needs_improvement(password): return not is_valid_password(password)

password = "abc123" needs_improvement = password_needs_improvement(password) print(f"Password needs improvement: {needs_improvement}") # Output: Password needs improvement: True

Double negation

value = True double_negated = not not value print(f"Double negated: {double_negated}") # Output: Double negated: True `

Operator Precedence

Understanding operator precedence is crucial when working with multiple logical operators in a single expression.

Precedence Order (Highest to Lowest):

| Precedence | Operator | Description | |------------|----------|-------------| | 1 | not | Logical NOT | | 2 | and | Logical AND | | 3 | or | Logical OR |

Examples Demonstrating Precedence:

`python

Without parentheses - following precedence rules

result1 = True or False and False print(result1) # Output: True (equivalent to: True or (False and False))

With parentheses - overriding precedence

result2 = (True or False) and False print(result2) # Output: False

Complex expression

a, b, c, d = True, False, True, False result3 = not a or b and c or d print(result3) # Output: False

Equivalent to: (not a) or (b and c) or d

Which is: False or False or False = False

Using parentheses for clarity

result4 = (not a) or (b and c) or d print(result4) # Output: False (same as above but clearer) `

Short-Circuit Evaluation

Python implements short-circuit evaluation for logical operators, which means that the evaluation stops as soon as the result is determined.

Short-Circuit with and

With the and operator, if the first operand is False, Python doesn't evaluate the second operand because the result will always be False.

`python def expensive_function(): print("Expensive function called") return True

def cheap_function(): print("Cheap function called") return False

Short-circuit example with and

result = cheap_function() and expensive_function() print(f"Result: {result}")

Output:

Cheap function called

Result: False

Note: expensive_function() is not called

Non-short-circuit example

result2 = True and expensive_function() print(f"Result2: {result2}")

Output:

Expensive function called

Result2: True

`

Short-Circuit with or

With the or operator, if the first operand is True, Python doesn't evaluate the second operand because the result will always be True.

`python def first_condition(): print("First condition evaluated") return True

def second_condition(): print("Second condition evaluated") return False

Short-circuit example with or

result = first_condition() or second_condition() print(f"Result: {result}")

Output:

First condition evaluated

Result: True

Note: second_condition() is not called

Non-short-circuit example

result2 = False or second_condition() print(f"Result2: {result2}")

Output:

Second condition evaluated

Result2: False

`

Practical Applications and Examples

Input Validation

`python def validate_registration_form(username, password, email, age): """ Validate user registration form with multiple conditions """ username_valid = len(username) >= 3 and len(username) <= 20 password_valid = len(password) >= 8 and any(c.isdigit() for c in password) and any(c.isupper() for c in password) email_valid = "@" in email and "." in email age_valid = age >= 13 and age <= 120 return username_valid and password_valid and email_valid and age_valid

Test the validation function

user_data = { "username": "john_doe", "password": "SecurePass123", "email": "john@example.com", "age": 25 }

is_valid = validate_registration_form(user_data) print(f"Registration form valid: {is_valid}") # Output: Registration form valid: True `

Access Control System

`python class AccessControl: def __init__(self): self.admin_users = ["admin", "superuser"] self.moderator_users = ["mod1", "mod2"] self.business_hours = (9, 17) # 9 AM to 5 PM def is_business_hours(self, current_hour): return self.business_hours[0] <= current_hour < self.business_hours[1] def can_access_admin_panel(self, username, current_hour, is_emergency=False): is_admin = username in self.admin_users during_hours = self.is_business_hours(current_hour) # Admin can access during business hours OR during emergency return is_admin and (during_hours or is_emergency) def can_moderate_content(self, username, current_hour): is_admin = username in self.admin_users is_moderator = username in self.moderator_users during_hours = self.is_business_hours(current_hour) # Admins can always moderate, moderators only during business hours return is_admin or (is_moderator and during_hours)

Usage example

access_control = AccessControl()

Test admin access

admin_access = access_control.can_access_admin_panel("admin", 14) # 2 PM print(f"Admin can access panel: {admin_access}") # Output: Admin can access panel: True

Test moderator access

mod_access = access_control.can_moderate_content("mod1", 20) # 8 PM print(f"Moderator can access: {mod_access}") # Output: Moderator can access: False `

Data Filtering and Search

`python class ProductFilter: def __init__(self, products): self.products = products def filter_products(self, min_price=0, max_price=float('inf'), category=None, in_stock=None, min_rating=0): """ Filter products based on multiple criteria using logical operators """ filtered_products = [] for product in self.products: price_match = min_price <= product['price'] <= max_price category_match = category is None or product['category'] == category stock_match = in_stock is None or product['in_stock'] == in_stock rating_match = product['rating'] >= min_rating # Product must match ALL criteria if price_match and category_match and stock_match and rating_match: filtered_products.append(product) return filtered_products def search_products(self, query): """ Search products by name or description """ query_lower = query.lower() results = [] for product in self.products: name_match = query_lower in product['name'].lower() desc_match = query_lower in product['description'].lower() # Match if query is in name OR description if name_match or desc_match: results.append(product) return results

Sample data

products = [ {"name": "Laptop", "price": 999, "category": "Electronics", "in_stock": True, "rating": 4.5, "description": "High-performance laptop"}, {"name": "Phone", "price": 699, "category": "Electronics", "in_stock": False, "rating": 4.2, "description": "Smartphone with great camera"}, {"name": "Book", "price": 29, "category": "Books", "in_stock": True, "rating": 4.8, "description": "Programming guide"}, {"name": "Headphones", "price": 199, "category": "Electronics", "in_stock": True, "rating": 4.0, "description": "Noise-canceling headphones"} ]

Usage example

product_filter = ProductFilter(products)

Filter electronics under $800 that are in stock

filtered = product_filter.filter_products(max_price=800, category="Electronics", in_stock=True) print(f"Filtered products: {len(filtered)} items")

Search for products containing "phone"

search_results = product_filter.search_products("phone") print(f"Search results: {len(search_results)} items") `

Common Patterns and Best Practices

Pattern 1: Default Value Assignment

`python def process_user_settings(settings=None): # Use or operator for default value assignment settings = settings or {} # Extract settings with defaults theme = settings.get('theme') or 'light' notifications = settings.get('notifications') or True language = settings.get('language') or 'en' return { 'theme': theme, 'notifications': notifications, 'language': language }

Usage

user_settings = process_user_settings({'theme': 'dark'}) print(user_settings) # Output: {'theme': 'dark', 'notifications': True, 'language': 'en'} `

Pattern 2: Validation Chains

`python def validate_email(email): """Comprehensive email validation using logical operators""" if not email: return False, "Email is required" # Basic format checks has_at = '@' in email has_dot = '.' in email not_empty = len(email.strip()) > 0 no_spaces = ' ' not in email basic_valid = has_at and has_dot and not_empty and no_spaces if not basic_valid: return False, "Invalid email format" # Advanced checks parts = email.split('@') if len(parts) != 2: return False, "Email must contain exactly one @ symbol" local, domain = parts local_valid = len(local) > 0 and not local.startswith('.') and not local.endswith('.') domain_valid = len(domain) > 0 and '.' in domain and not domain.startswith('.') and not domain.endswith('.') if not (local_valid and domain_valid): return False, "Invalid email structure" return True, "Email is valid"

Test the validation

test_emails = [ "user@example.com", "invalid.email", "@example.com", "user@", "user name@example.com" ]

for email in test_emails: is_valid, message = validate_email(email) print(f"{email}: {message}") `

Pattern 3: Feature Flags and Permissions

`python class FeatureManager: def __init__(self): self.features = { 'beta_ui': False, 'advanced_analytics': True, 'experimental_search': False, 'premium_support': True } self.user_permissions = { 'admin': ['all'], 'premium': ['advanced_analytics', 'premium_support'], 'beta_tester': ['beta_ui', 'experimental_search'], 'regular': [] } def can_access_feature(self, user_type, feature_name): """Check if user can access a specific feature""" # Feature must be enabled AND user must have permission feature_enabled = self.features.get(feature_name, False) # Admin has access to all features if user_type == 'admin': return feature_enabled # Check specific permissions user_features = self.user_permissions.get(user_type, []) has_permission = feature_name in user_features return feature_enabled and has_permission def get_available_features(self, user_type): """Get all features available to a user type""" available = [] for feature_name, enabled in self.features.items(): if self.can_access_feature(user_type, feature_name): available.append(feature_name) return available

Usage example

feature_manager = FeatureManager()

Test different user types

user_types = ['admin', 'premium', 'beta_tester', 'regular']

for user_type in user_types: available_features = feature_manager.get_available_features(user_type) print(f"{user_type} user can access: {available_features}") `

Advanced Logical Operations

Combining with Comparison Operators

`python def analyze_student_performance(scores, attendance, assignments_completed): """Analyze student performance using complex logical operations""" # Calculate averages avg_score = sum(scores) / len(scores) if scores else 0 completion_rate = assignments_completed / 10 # Assuming 10 total assignments # Define performance criteria excellent = (avg_score >= 90) and (attendance >= 95) and (completion_rate >= 0.95) good = (avg_score >= 80) and (attendance >= 85) and (completion_rate >= 0.80) and not excellent satisfactory = (avg_score >= 70) and (attendance >= 75) and (completion_rate >= 0.70) and not (excellent or good) needs_improvement = not (excellent or good or satisfactory) # Additional flags perfect_attendance = attendance == 100 honor_roll = (avg_score >= 85) and (attendance >= 90) at_risk = (avg_score < 60) or (attendance < 70) or (completion_rate < 0.50) return { 'avg_score': avg_score, 'completion_rate': completion_rate, 'performance_level': 'Excellent' if excellent else 'Good' if good else 'Satisfactory' if satisfactory else 'Needs Improvement', 'perfect_attendance': perfect_attendance, 'honor_roll': honor_roll, 'at_risk': at_risk }

Test with sample data

student_data = analyze_student_performance([85, 92, 78, 88, 95], 88, 9) print("Student Performance Analysis:") for key, value in student_data.items(): print(f" {key}: {value}") `

Working with Collections

`python def analyze_survey_data(responses): """Analyze survey responses using logical operators with collections""" total_responses = len(responses) if total_responses == 0: return {"error": "No responses to analyze"} # Count responses by category satisfied = sum(1 for r in responses if r['satisfaction'] >= 4) young_adults = sum(1 for r in responses if 18 <= r['age'] <= 35) high_income = sum(1 for r in responses if r['income'] >= 75000) # Complex conditions satisfied_young_adults = sum(1 for r in responses if (r['satisfaction'] >= 4) and (18 <= r['age'] <= 35)) dissatisfied_or_low_income = sum(1 for r in responses if (r['satisfaction'] < 3) or (r['income'] < 30000)) premium_segment = sum(1 for r in responses if (r['income'] >= 100000) and (r['satisfaction'] >= 4) and (r['age'] >= 25)) # Calculate percentages satisfaction_rate = (satisfied / total_responses) * 100 young_adult_rate = (young_adults / total_responses) * 100 return { 'total_responses': total_responses, 'satisfaction_rate': round(satisfaction_rate, 2), 'young_adult_rate': round(young_adult_rate, 2), 'satisfied_young_adults': satisfied_young_adults, 'dissatisfied_or_low_income': dissatisfied_or_low_income, 'premium_segment': premium_segment }

Sample survey data

survey_responses = [ {'satisfaction': 5, 'age': 28, 'income': 65000}, {'satisfaction': 3, 'age': 45, 'income': 85000}, {'satisfaction': 4, 'age': 32, 'income': 120000}, {'satisfaction': 2, 'age': 29, 'income': 25000}, {'satisfaction': 5, 'age': 38, 'income': 95000} ]

analysis = analyze_survey_data(survey_responses) print("Survey Analysis Results:") for key, value in analysis.items(): print(f" {key}: {value}") `

Performance Considerations

Optimizing Logical Operations

`python import time

def performance_comparison(): """Demonstrate performance differences in logical operations""" # Setup test data large_list = list(range(1000000)) def expensive_check(x): # Simulate expensive operation return sum(range(x % 100)) > 1000 def cheap_check(x): # Simple check return x % 2 == 0 # Test 1: Order matters in AND operations start_time = time.time() count1 = sum(1 for x in large_list[:10000] if cheap_check(x) and expensive_check(x)) time1 = time.time() - start_time start_time = time.time() count2 = sum(1 for x in large_list[:10000] if expensive_check(x) and cheap_check(x)) time2 = time.time() - start_time print(f"Cheap first: {time1:.4f}s, Expensive first: {time2:.4f}s") print(f"Performance improvement: {((time2 - time1) / time2) * 100:.1f}%")

Run performance comparison

performance_comparison() `

Error Handling with Logical Operators

`python def safe_division_with_validation(a, b, allow_negative=False): """Demonstrate error handling using logical operators""" # Input validation using logical operators valid_inputs = (isinstance(a, (int, float)) and isinstance(b, (int, float)) and not (allow_negative is False and (a < 0 or b < 0))) if not valid_inputs: return None, "Invalid input parameters" # Division by zero check if b == 0: return None, "Division by zero error" # Perform calculation result = a / b # Result validation import math if math.isnan(result) or math.isinf(result): return None, "Invalid mathematical result" return result, "Success"

Test cases

test_cases = [ (10, 2, True), # Valid case (10, 0, True), # Division by zero (-5, 2, False), # Negative not allowed ("10", 2, True), # Invalid type (10.5, 2.5, True) # Valid floats ]

for a, b, allow_neg in test_cases: result, message = safe_division_with_validation(a, b, allow_neg) print(f"divide({a}, {b}, allow_negative={allow_neg}): {result} - {message}") `

Summary Table of Logical Operators

| Operator | Symbol | Description | Example | Result | |----------|--------|-------------|---------|--------| | AND | and | Returns True if both operands are True | True and False | False | | OR | or | Returns True if at least one operand is True | True or False | True | | NOT | not | Returns the opposite boolean value | not True | False |

Common Use Cases Summary

| Use Case | Recommended Operator | Example Scenario | |----------|---------------------|------------------| | Input Validation | and | All fields must be valid | | Access Control | or | User is admin OR moderator | | Feature Toggles | and | Feature enabled AND user has permission | | Default Values | or | Use provided value OR default | | Negation | not | Opposite of a condition | | Error Handling | and/or | Multiple validation checks |

Logical operators in Python are powerful tools that enable developers to create sophisticated decision-making logic. By understanding their behavior, precedence rules, and performance characteristics, you can write more efficient and maintainable code. Remember to use parentheses for clarity when combining multiple operators, and take advantage of short-circuit evaluation to optimize performance in your applications.

Tags

  • boolean logic
  • conditional statements
  • control flow
  • logical operators
  • python basics

Related Articles

Related Books - Expand Your Knowledge

Explore these Python books to deepen your understanding:

Browse all IT books

Popular Technical Articles & Tutorials

Explore our comprehensive collection of technical articles, programming tutorials, and IT guides written by industry experts:

Browse all 8+ technical articles | Read our IT blog

Python Logical Operators: and, or, not - Complete Guide