Skip to content

Instantly share code, notes, and snippets.

@ebridges
Created August 7, 2024 15:24
Show Gist options
  • Save ebridges/259f99f748b4042c96a8622fde7b729a to your computer and use it in GitHub Desktop.
Save ebridges/259f99f748b4042c96a8622fde7b729a to your computer and use it in GitHub Desktop.
Python Language Features

Python language features

Standard control structures

Conditional statements

  • if statement
if condition:
	# code to execute if condition is true
  • if-else statement
if condition:
	# code to execute if condition is true
else:
	# code to execute if condition is false
  • if-elif-else statement
if condition1:
	# code to execute if condition1 is true
elif condition2:
	# code to execute if condition2 is true
else:
	# code to execute if both conditions are false

Looping statements

  • for loop
for item in iterable:
	# code to execute for each item in iterable
  • for-else
for item in iterable:
	if condition:
		break
else:
	# code here runs if the loop didn't break
  • while loop
while condition:
	# code to execute while condition is true
  • while-else loop
while condition:
	if other_condition:
		break
else:
	# Code here runs if the loop didn't break

Control flow statements

  • break statement
for item in iterable:
	if condition:
		break # exits the loop
  • continue statement
for item in iterable:
	if condition:
		continue # skips to the next iteration
  • pass statement
if condition:
	pass # does nothing, can be a placeholder for future code
  • match statement
def http_status(status):
	match status:
		case 200:
			return 'OK'
		case 404:
			return 'Not found'
		case _:
			return 'Unknown'

Exception handling

  • try-except
try:
	# code that may raise `SomeException`
except SomeException as e:
	# code to handle the exception
  • try-except-finally
try:
	# code that may raise `SomeException`
except SomeException as e:
	# code to handle the exception
finally:
	# code that will run no matter what
  • try-except-else-finally
try:
	# code that may raise `SomeException`
except SomeException as e:
	# code to handle the exception
else:
	# code that runs if no exceptions were raised
finally:
	# code that will run no matter what

Function definitions

def function_name(parameters):
	# code to execute with given parameters 
	# when the function is called
	return value

Class definitions

class Person:
	species = "Homo sapiens" # Class variable

	@staticmethod
	def species_name():
	'''
	Static methods are used to group functions that have some
	logical connection with the class but do not need or should
	not modify class or instance state.
	'''
		return Person.species

	@classmethod
	def build(cls, name):
	'''
	Class methods are used for factory methods that instantiate
	instances in different ways, or for methods that operate on
	the class itself rather than on instances.
	'''
		return cls(name, 0)
	
	def __init__(self, name, age):
		# initializer method
		self.name = name # instance variable
		self.age = age
	def greet(self):
		# method definition
		return f'I am {self.name} and I am {self.age} years old.
	def __str__(self):
		return self.greet()

Asynchronous programming

import asyncio
import sys
async def main():
	print('Hello', end=' ')
	sys.stdout.flush()
	await asyncio.sleep(3)
	print('World!')

asyncio.run(main())

Miscellaneous

  • with statement - simplifies exception handling and resource management, ensuring that resources are properly cleaned up after use.
with open('file.txt', 'r') as file:
	content = file.read()
# no need to explicitly close `file` even if exception is thrown
  • f-strings - provide a more readable and concise way to format strings.
name = 'World'
message = f'Hello, {name}!'

Extended iterable unpacking - allows for flexible unpacking of iterables.

a, *b, c = [1, 2, 3, 4, 5]
# a = 1, b = [2, 3, 4], c = 5

Modules

Defining a module

  • A module is defined by creating a file with a .py extension. The file name becomes the module name.
  • For example:
# mymodule.py

# This is a simple function defined in the module
def greet(name):
    return f"Hello, {name}!"

# This is a class defined in the module
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"{self.name} is {self.age} years old."

# Module-level variable
version = "1.0"

Using a module

  • import statement
    • The module is used by importing it in another python script.
import mymodule

print(mymodule.greet('Alice'))
# prints "Hello, Alice!"

person = mymodule.Person('Bob', 30)
print(person)
# prints: "Bob is 30 years old."

print(f'Module version: {mymodule.version}')
# prints: "Module version: 1.0"
  • import...as statement
  • Used to create an alias for the module
# Import the module with an alias
import mymodule as mm

print(mm.greet("Alice"))

person = mm.Person("Bob", 30)
print(person)

print(f"Module version: {mm.version}")
  • Can be used on specific components being imported
# Import specific components with aliases
from mymodule import greet as hello, Person as Individual, version as ver

print(hello("Alice"))

person = Individual("Bob", 30)
print(person)

print(f"Module version: {ver}")
  • from...import statement
    • You can also import specific components (functions, classes, variables) from the module.
# Import specific components
from mymodule import greet, Person, version

print(greet("Alice"))

person = Person("Bob", 30)
print(person)

print(f"Module version: {version}")

Creating a package

mkdir mypackage
cd mypackage
touch __init__.py
echo 'my_variable=12345' > mymodule.py

Using a package

from mypackage import mymodule
print(mymodule.my_variable)
# prints: 12345

Standard data types

Lists

  • Can store elements of different data types.
  • More flexible but less memory-efficient.
  • Commonly used for general-purpose collections.
my_list = [1, 2, 3, "four", 5.0]
  • Accessing elements
print(my_list[0])  # Output: 1
print(my_list[-1]) # Output: 5.0
  • Modify elements
my_list[1] = "two"
  • Add elements
my_list.append(6)
my_list.insert(1, "inserted")
  • Remove elements
my_list.remove("four") # Removes element matching input
last_element = my_list.pop()  # Removes & returns last element
  • Length of list
len(my_list)
  • Slicing
subset = my_list[1:3] # elements from index 1 to 2
  • List comprehension
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]

Sorted List

Python doesn’t have support for lists that maintain their order as you add to them. Here’s a way to do that:

import bisect

class sorted_list(list):
    def __init__(self, *args):
        super().__init__(*args)
        for value in args:
            self.append(value)
    
    def append(self, value):
        bisect.insort(self, value)

    def extend(self, values):
        for value in values:
            self.append(value)

This can be used with defaultdict to maintain a dictionary whose values are sorted lists:

from collections import defaultdict

sorted_dict = defaultdict(sorted_list)

# Example usage
sorted_dict['a'].append(5)
sorted_dict['a'].append(7)
sorted_dict['a'].append(1)
sorted_dict['a'].append(3)
sorted_dict['b'].append(8)
sorted_dict['b'].append(4)
sorted_dict['b'].append(2)
sorted_dict['b'].append(6)

# Print the dictionary
for key, sorted_list in sorted_dict.items():
    print(f"Key: {key}, Sorted List: {sorted_list}")

Arrays

  • Require elements to be of the same data type.

  • More memory-efficient and faster for numerical operations.

  • Suitable for numerical data and mathematical operations.

  • Provided by the array module or libraries like numpy

  • Import and definition

import array as arr
my_array = arr.array('i', [1, 2, 3])  # 'i' denotes array of int
  • Other operations are the same as with [[#Lists]]

  • Examples:

import array as arr
my_array = arr.array('i', [1, 2, 3, 4, 5])
my_array.append(6)
print(my_array)  # Output: array('i', [1, 2, 3, 4, 5, 6])

Numpy library

  • Supports multi-dimensional arrays (e.g., matrices).
  • Provides a wide range of mathematical and statistical functions.
  • Import and definition
import numpy as np
my_array = np.array([1, 2, 3, 4, 5])
  • Example
import numpy as np
my_array = np.array([1, 2, 3, 4, 5])
print(my_array)  # Output: [1 2 3 4 5]

# Creating a 2D array (matrix)
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix)

Dictionaries

  • Dictionaries are mutable, unordered collections of key-value pairs. They are optimized for retrieving values when the key is known.
  • Keys: Must be unique and immutable (e.g., strings, numbers, tuples).
  • Values: Can be of any data type and can be duplicated.
  • Order: In Python 3.7 and later, dictionaries maintain insertion order.
my_dict = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
}
  • Accessing elements
value = my_dict["key1"] # Raises `KeyError` if not found.
value = my_dict.get("key4", value='not found') # returns 'not found', or None if `value` not specified.
  • Add or update elements
my_dict["key4"] = "value4"  # Adds a new key-value pair
my_dict["key1"] = "new_value1"  # Updates the value for "key1"
  • Remove elements
value = my_dict.pop("key2") # Removes key2 and returns its value
del my_dict["key3"] # Removes key3 from the dictionary
my_dict.clear() # Removes all elements
  • Checking for keys
if "key1" in my_dict:
    print("key1 is in the dictionary")
  • Iterating Over Elements
for key in my_dict:
    print(key, my_dict[key])

for key, value in my_dict.items():
    print(key, value)
  • Dictionary comprehension
squared_numbers = {x: x*x for x in range(5)} 
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment