Python Type Casting Lab

Lab 1: The “Log Parser” (String to Int) Scenario: You read a response time from a log file, but it has “ms” at the end.

raw_time = "200ms"

# Step 1: Clean the data (Remove 'ms')
clean_time_str = raw_time.replace("ms", "")

# Step 2: Cast to Integer
time_int = int(clean_time_str)

# Step 3: Logic
if time_int > 100:
    print("Alert: Latency is high!")

Lab 2: The Data Loss Experiment (Float to Int)

pi = 3.14159
gravity = 9.8

# Implicit (No data loss)
combined = pi + gravity
print(f"Implicit Sum: {combined}") # 12.94159

# Explicit (Data loss)
truncated_pi = int(pi)
print(f"Integer Pi: {truncated_pi}") # 3 (Decimal lost)

Lab 3: The “Env Var” List Parser (String $\rightarrow$ List)

Scenario: You are configuring a firewall script. The allowed IP addresses are passed as a single Environment Variable string (e.g., "10.0.0.1,10.0.0.2").

  • The Trap: If you use list(), it splits the string into individual characters!
  • The Fix: You must use the .split() string method to create a list of items.
import os

# Simulating an Environment Variable
# format: "IP1,IP2,IP3"
env_allowed_ips = "192.168.1.10,192.168.1.20,10.5.5.1"

# --- WRONG WAY (Casting) ---
# This breaks the string into characters: ['1', '9', '2', ...]
wrong_list = list(env_allowed_ips)
print(f"Wrong List size: {len(wrong_list)}") # Output: 34 (Huge list of chars!)

# --- CORRECT WAY (Splitting) ---
# This splits the string at every comma
correct_list = env_allowed_ips.split(",")
print(f"Correct List: {correct_list}") 
# Output: ['192.168.1.10', '192.168.1.20', '10.5.5.1']

# Architect Bonus: Clean up spaces just in case "IP, IP" was used
cleaned_list = [ip.strip() for ip in correct_list]
  • Architect Insight: list() constructor is for iterables (things you can loop over). .split() is for separators. Don’t confuse them!

Lab 4: The “Legacy API” Fixer (Bulk Conversion)

Scenario: You are consuming an old legacy API that returns everything as strings, even numbers and booleans. You need to sanitize this data before storing it in your modern database.

# The messy data from the old API
legacy_payload = {
    "server_id": "9901",
    "is_active": "true",  # Lowercase string
    "cpu_load": "45.5",
    "tags": "web,prod,aws"
}

# The Sanitizer Logic
cleaned_data = {
    # 1. Cast String to Integer
    "id": int(legacy_payload["server_id"]),
    
    # 2. Compare String to Boolean (Safest way)
    "active": legacy_payload["is_active"].lower() == "true",
    
    # 3. Cast String to Float
    "load": float(legacy_payload["cpu_load"]),
    
    # 4. Split String to List
    "tags": legacy_payload["tags"].split(",")
}

print("Sanitized Data Schema:")
print(cleaned_data)
# Output: {'id': 9901, 'active': True, 'load': 45.5, 'tags': ['web', 'prod', 'aws']}

Lab 5: The “Hash Handler” (Bytes $\rightarrow$ Hex String)

Scenario: You are generating a SHA-256 checksum for a file to verify its integrity.

  • The Challenge: Hashing libraries return bytes (binary data like b'\xea\x98...'). You cannot print this effectively or save it to a text report.
  • The Fix: You must convert (decode) the bytes into a Hexadecimal String.
import hashlib

data = "MySecurePassword123"

# Step 1: Encode String to Bytes (Computers need bytes for math)
data_bytes = data.encode("utf-8") 

# Step 2: Generate Hash (Returns binary object)
hash_object = hashlib.sha256(data_bytes)
binary_hash = hash_object.digest()

print(f"Raw Binary: {binary_hash}") 
# Output: b'...' (Unreadable garbage characters)

# Step 3: Convert to Hex String (The "DevOps" way)
# .hexdigest() handles the casting from bytes to hex string automatically
readable_hash = hash_object.hexdigest()

print(f"Readable Hash: {readable_hash}")
# Output: 9f86d081884c7d659... (Standard readable hash)
  • Architect Insight: In Security Automation, you will constantly convert between String (utf-8) and Bytes (b''). Remember: str.encode() $\rightarrow$ Bytes, bytes.decode() $\rightarrow$ String.

Lab 6: Robust Safe-Casting Function

Scenario: You are building a utility library for your team. You want a function to_int that never crashes your script, even if the input is garbage.

def safe_int_cast(value, default=0):
    """
    Tries to convert value to int. 
    If it fails (None, text, etc.), returns the default value.
    """
    try:
        # Handle cases where input is purely None
        if value is None:
            return default
            
        # Try to cast
        return int(float(value)) # Using float first handles "5.5" string cases
        
    except (ValueError, TypeError):
        print(f"Warning: Could not cast '{value}'. Using default.")
        return default

# Test Cases
print(safe_int_cast("100"))       # 100
print(safe_int_cast("50.99"))     # 50 (Truncated)
print(safe_int_cast("NotNumber")) # 0 (Default, warning printed)
print(safe_int_cast(None))        # 0 (Default)
  • Architect Insight: Writing “Wrapper Functions” like this is a hallmark of a Senior Developer. It makes your main code clean and error-proof.

Lab 7: The “Octal” Permission Trap

Scenario: You are setting file permissions (chmod). Linux permissions like 0777 are Octal numbers, not Decimals.

  • The Trap: int("0777") converts it to Decimal 777. This is wrong for os.chmod!
  • The Fix: Tell int() the base.
permission_str = "0755"

# WRONG: Default is base 10
wrong_perm = int(permission_str) 
print(f"Base 10 Value: {wrong_perm}") # 755 (Decimal)

# CORRECT: Base 8 (Octal)
# This is what Linux expects for permissions
correct_perm = int(permission_str, 8)
print(f"Base 8 Value:  {correct_perm}") # 493 (Decimal equivalent of 0o755)

# Proof using Python's oct() display
print(f"Octal Display: {oct(correct_perm)}") # 0o755

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top