Mastering Advanced Python Concepts with Flashcards

Table of Contents

Advanced Python Flashcards

Decorators   drill advanced_python

Front

What are decorators in Python and how are they used?

Back

Decorators are functions that modify the behavior of other functions or methods without changing their source code. They use the @decorator syntax and are commonly used for logging, timing, authentication, and more.

Example:

def log_function_call(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function: {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@log_function_call
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Context Managers   drill advanced_python

Front

Explain context managers in Python and provide an example.

Back

Context managers are objects that define the runtime context to be established when executing a with statement. They are used to manage resources, ensuring proper acquisition and release.

Example using a custom context manager:

class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None

    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()

with FileManager('example.txt', 'w') as f:
    f.write('Hello, World!')

Metaclasses   drill advanced_python

Front

What are metaclasses in Python and how are they used?

Back

Metaclasses are classes for classes. They define how a class behaves and are used to automatically modify or enhance classes at creation time. The type() function is the default metaclass.

Example:

class MyMetaclass(type):
    def __new__(cls, name, bases, attrs):
        # Add a new method to the class
        attrs['custom_method'] = lambda self: print("This is a custom method")
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMetaclass):
    pass

obj = MyClass()
obj.custom_method()  # Outputs: This is a custom method

Generators and Coroutines   drill advanced_python

Front

Explain the difference between generators and coroutines in Python.

Back

Generators are functions that use the yield keyword to produce a series of values lazily. They are primarily used for iteration.

Coroutines are more general and can consume values (with yield expressions), produce values (with yield statements), and have multiple entry points for code execution.

Example of a generator:

def countdown(n):
    while n > 0:
        yield n
        n -= 1

for num in countdown(5):
    print(num)

Example of a coroutine:

def grep(pattern):
    print(f"Searching for {pattern}")
    while True:
        line = yield
        if pattern in line:
            print(line)

g = grep("python")
next(g)  # Prime the coroutine
g.send("python is great")
g.send("java is also cool")
g.send("python is powerful")

Descriptors   drill advanced_python

Front

What are descriptors in Python and how do they work?

Back

Descriptors are objects that define how attribute access on other objects should behave. They implement at least one of the methods: _get_(), _set_(), or _delete_().

Example of a descriptor for type checking:

class TypeChecked:
    def __init__(self, name, type):
        self.name = name
        self.type = type

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, self.type):
            raise TypeError(f"{self.name} must be of type {self.type}")
        instance.__dict__[self.name] = value

class Person:
    name = TypeChecked("name", str)
    age = TypeChecked("age", int)

    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 30)
print(p.name, p.age)  # Alice 30
p.age = "thirty"  # Raises TypeError

Author: Jason Walsh

j@wal.sh

Last Updated: 2024-08-14 06:08:49