Python notes #2 (Data types)

post-title

Introduction to Data Types in Python

  • Python is dynamically typed, meaning you don’t need to declare a variable’s type explicitly. The interpreter assigns a type at runtime based on the value.
x = 10       # x is an integer
x = "Hello" # Now x is a string

Built-in Data Types in Python

  • Numeric — intfloatcomplex
  • Sequence — strlisttuplerange
  • Set — setfrozenset
  • Mapping — dict
  • Boolean — bool
  • Binary — bytesbytearraymemoryview
  • NoneType — None
print(type(10))         # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type([1, 2, 3])) # <class 'list'>
print(type(None)) # <class 'NoneType'>

Numeric Data Types

Integer (int)

  • Represents whole numbers (positive, negative, or zero).
  • No limit on size (except memory constraints).

Floating-Point (float)

  • Represents decimal numbers or numbers with a fractional part.
  • Uses IEEE 754 double-precision floating-point format internally.

Complex Numbers (complex)

  • Represents numbers in the form a + bj, where j is the imaginary unit.
  • Used in advanced mathematical computations.
# Integer (`int`) Methods
x = -10

print(abs(x)) # 10 (Absolute value)
print(bin(10)) # '0b1010' (Binary representation)
print(hex(255)) # '0xff' (Hexadecimal representation)
print(oct(8)) # '0o10' (Octal representation)
print(int("1001", 2)) # 9 (Convert binary string to integer)
# Floating-Point (`float`) Methods
y = 3.14159
print(round(y, 2)) # 3.14 (Round to 2 decimal places)
print(pow(2, 3)) # 8 (2^3, equivalent to 2**3)
print(float("10.5")) # 10.5 (Convert string to float)
print(int(4.7)) # 4 (Convert float to integer)
print(y.is_integer()) # False (Checks if float has no decimal part)

Sequence Data Types

String (str)

  • A sequence of Unicode characters enclosed in single or double quotes.
  • Immutable (cannot be modified after creation).
s = "hello world"
print(s.upper()) # "HELLO WORLD" (Convert to uppercase)
print(s.lower()) # "hello world" (Convert to lowercase)
print(s.title()) # "Hello World" (Title case)
print(s.strip()) # "hello world" (Removes leading/trailing spaces)
print(s.replace("world", "Python")) # "hello Python" (Replace substring)
print(s.split()) # ['hello', 'world'] (Split string into list)
print("-".join(["Hello", "world"])) # "Hello-world" (Join list elements)
print(s.find("world")) # 6 (Index of first occurrence of substring)
print(s.count("l")) # 3 (Count occurrences of character)

List (list)

  • A mutable ordered collection that can hold mixed data types.
# Creating a list with 2 items
my_list = [3, 1]

# Adding Elements
my_list.append(5) # [3, 1, 5] (Adds 5 at the end)
my_list.insert(1, 10) # [3, 10, 1, 5] (Inserts 10 at index 1)
my_list.extend([6, 7]) # [3, 10, 1, 5, 6, 7] (Concatenates another list)
# Removing Elements
my_list.pop() # [3, 10, 1, 5, 6] (Removes last element)
my_list.pop(1) # [3, 1, 5, 6] (Removes element at index 1)
my_list.remove(5) # [3, 1, 6] (Removes first occurrence of 5)
my_list.clear() # [] (Removes all elements)
# Rebuilding the list for further operations
my_list = [3, 1]
# Sorting & Reversing
my_list.sort() # [1, 3] (Sorts the list in ascending order)
my_list.reverse() # [3, 1] (Reverses the list)
sorted_list = sorted(my_list) # Returns a new sorted list
# Checking & Finding Elements
print(3 in my_list) # True (Check existence)
print(my_list.count(1)) # 1 (Count occurrences of 1)
print(my_list.index(3)) # 0 (Find index of 3)
# Copying the List
copy_list = my_list.copy() # Creates a shallow copy of the list
# List Length, Max, Min, and Sum
print(len(my_list)) # 2 (Number of elements)
print(max(my_list)) # 3 (Largest element)
print(min(my_list)) # 1 (Smallest element)
print(sum(my_list)) # 4 (Sum of all elements)
# List Comprehension (Generating a List of Squares)
squares = [x**2 for x in range(2)] # [0, 1]

List Comprehension (list)

# Creating a list of squares
squares = [x**2 for x in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]

# Filtering even numbers
evens = [x for x in range(10) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8]
# Creating a list of tuples
pairs = [(x, x**2) for x in range(5)]
print(pairs) # [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16)]

Tuple (tuple)

  • Similar to a list but immutable (cannot be modified).
t = (1, 2, 3, 2, 4)

print(t.count(2)) # 2 (Count occurrences of 2)
print(t.index(3)) # 2 (Find index of value 3)

Tuple Comprehension (tuple)

# Creating a tuple of squares
squares_tuple = tuple(x**2 for x in range(1, 6))
print(squares_tuple) # (1, 4, 9, 16, 25)

Range (range)

r = range(1, 10, 2)  # Creates range from 1 to 9 with step 2

print(list(r)) # [1, 3, 5, 7, 9] (Convert range to list)
print(r.start) # 1 (Start value)
print(r.stop) # 10 (Stop value)
print(r.step) # 2 (Step value)

Set Data Types

Set (set)

  • Stores only unique elements (duplicates are removed automatically).
  • Supports set operations like union, intersection, difference.
  • Unordered (no indexing or slicing).
  • Mutable (can add or remove elements).

Frozenset (frozenset)

  • Similar to a set but immutable (cannot be modified after creation).
  • Useful when you need a hashable set (e.g., as a dictionary key).
s = {1, 2, 3}

# Adding and Removing Elements
s.add(4) # {1, 2, 3, 4}
s.remove(2) # {1, 3, 4} (Error if not found)
s.discard(5) # No error if element doesn't exist
s.clear() # {} (Removes all elements)
# Set Operations
s1 = {1, 2, 3}
s2 = {3, 4, 5}
print(s1.union(s2)) # {1, 2, 3, 4, 5} (Combine sets)
print(s1.intersection(s2)) # {3} (Common elements)
print(s1.difference(s2)) # {1, 2} (Elements in s1 but not in s2)
print(s1.symmetric_difference(s2)) # {1, 2, 4, 5} (Elements in one set)
# Membership Testing
print(2 in s1) # True
print(5 in s1) # False

Set Comprehension (set)

# Creating a set of squares
squares_set = {x**2 for x in range(1, 6)}
print(squares_set) # {1, 4, 9, 16, 25}

# Extracting unique vowels from a string
vowels = {char for char in "hello world" if char in "aeiou"}
print(vowels) # {'o', 'e'}

Mapping Data Type

Dictionary (dict)

# Dictionary Keys, Values, and Items
print(person.keys()) # dict_keys(['name', 'age'])
print(person.values()) # dict_values(['Alice', 26])
print(person.items()) # dict_items([('name', 'Alice'), ('age', 26)])

# Checking if a Key Exists
print("name" in person) # True
print("email" in person) # False
# Merging Dictionaries
person.update({"country": "USA", "age": 27})
print(person) # {'name': 'Alice', 'age': 27, 'country': 'USA'}
# Clearing a Dictionary
person.clear() # {}

Dictionary Comprehension

# Creating a dictionary with squares of numbers
squares = {x: x**2 for x in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
  • A dictionary in Python is a collection of key-value pairs where each key is unique. It is mutable and allows fast lookups.

Boolean Data Type

Boolean Data Type (bool)

  • The Boolean (bool) data type represents True or False values. It is a subclass of int, where: True is equivalent to 1 False is equivalent to 0
x = True
y = False
print(type(x)) # <class 'bool'>
print(int(x), int(y)) # 1 0

Truthy and Falsy Values

  • Falsy values (Evaluates to False): 0, “”, [], {}, set(), None, False
  • Truthy values (Evaluates to True): Everything else
print(bool(0))      # False
print(bool("")) # False
print(bool([])) # False
print(bool(100)) # True
print(bool("Hello")) # True

Binary Data Types

bytes (Immutable)

b = bytes([65, 66, 67])  # ASCII values for 'A', 'B', 'C'
print(b) # b'ABC'
print(b[0]) # 65 (Accessing byte value)

bytearray (Mutable)

ba = bytearray([65, 66, 67])
ba[1] = 68 # Modifying byte value
print(ba) # bytearray(b'ADC')

memoryview (Efficient Slicing)

bv = memoryview(b"Hello")
print(bv[1:4].tobytes()) # b'ell' (Slicing without copying data)

Use Cases

  • Handling binary files (images, audio, video)
  • Efficient data transfer in networking
  • Working with low-level operations (e.g., encryption, compression)

Type Conversion and Type Casting

Implicit Type Conversion (Automatic)

x = 10   # int
y = 2.5 # float
result = x + y # int + float → float
print(result, type(result)) # 12.5 <class 'float'>

Explicit Type Conversion (Casting)

# Convert to Integer
print(int(3.7)) # 3 (float → int)
print(int("10")) # 10 (str → int)

# Convert to Float
print(float(5)) # 5.0 (int → float)
# Convert to String
print(str(100)) # "100" (int → str)
# Convert to List, Tuple, Set
print(list("abc")) # ['a', 'b', 'c']
print(tuple([1, 2, 3])) # (1, 2, 3)
print(set([1, 2, 2, 3])) # {1, 2, 3}

Boolean Conversion

print(bool(0))    # False
print(bool(10)) # True
print(bool("")) # False
print(bool("Python")) # True

Mutable vs. Immutable Data Types

Mutable Data Types (Can be Modified)

  • Lists (list)
  • Dictionaries (dict)
  • Sets (set)
  • Bytearrays (bytearray)

Immutable Data Types (Cannot be Modified)

  • Integers (int)
  • Floats (float)
  • Strings (str)
  • Tuples (tuple)
  • Frozen Sets (frozenset)
  • Bytes (bytes)

Special Data Type: NoneType

  • Python has a special data type called NoneType, which has only one value: None. It represents the absence of a value or a null value in Python.
x = None
print(x) # None
print(type(x)) # <class 'NoneType'>

def example():
pass # No return statement
print(example()) # None
value = None # Assign None until a real value is provided
x = None
if x is None:
print("x has no value") # This runs

Advanced Topics

Type Hints and Static Typing (typing module)
Python supports optional type hints for better code readability and static analysis.

from typing import List, Dict

def add_numbers(a: int, b: int) -> int:
return a + b
def get_names() -> List[str]:
return ["Alice", "Bob"]

Custom Data Types with Classes
You can define custom data types using Python classes.

class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age

p = Person("Alice", 25)
print(p.name) # Alice

dataclass for Structured Data
Python’s dataclass provides a simple way to create data objects.

from dataclasses import dataclass

@dataclass
class Employee:
name: str
salary: float
e = Employee("Bob", 50000)
print(e) # Employee(name='Bob', salary=50000)

Memory Optimization with __slots__
Using __slots__ reduces memory usage by preventing dynamic attribute creation.

class Person:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age

p = Person("Alice", 30)
# p.address = "New York" # ❌ Error! `address` is not allowed.

Immutable Data with NamedTuple
NamedTuple is an immutable, lightweight alternative to classes.

from typing import NamedTuple

class Point(NamedTuple):
x: int
y: int
p = Point(3, 4)
print(p.x) # 3
# p.x = 5 # ❌ Error! NamedTuple is immutable.

Using collections for Specialized Data Types
The collections module provides enhanced data structures.

from collections import defaultdict, Counter

# defaultdict (Default value for missing keys)
d = defaultdict(int)
d["a"] += 1
print(d) # {'a': 1}
# Counter (Counts occurrences in an iterable)
c = Counter("banana")
print(c) # Counter({'a': 3, 'n': 2, 'b': 1})

enum for Defining Constant Values
Enum is used to define named constant values.

from enum import Enum

class Status(Enum):
PENDING = 1
COMPLETED = 2
FAILED = 3
print(Status.PENDING) # Status.PENDING
print(Status.PENDING.value) # 1
Top