1. Learn the Basics
Python is a high-level, interpreted, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation. Python is dynamically-typed and garbage-collected.
- official Python Website
- article Python - Wiki
- article Tutorial Series: How to Code in Python
- article Google’s Python Class
- article W3Schools - Python Tutorial
- video Learn Python - Full Course
- feed Explore top posts about Python
◇Basics Syntax
Setup the environment for python and get started with the basics.
- article W3Schools - Python
- article Python Basics
- article Learn X in Y Minutes / Python
- video Python for Beginners - Learn Python in 1 Hour
◇Variables and Data Types
Variables are used to store information to be referenced and manipulated in a computer program. They also provide a way of labeling data with a descriptive name, so our programs can be understood more clearly by the reader and ourselves. It is helpful to think of variables as containers that hold information. Their sole purpose is to label and store data in memory. This data can then be used throughout your program.
- article Variables in Python
- article W3Schools — Python Variables
- article Python Data Types
- article Python for Beginners: Data Types
- video Python Variables and Data Types
◇Conditionals
Conditional Statements in Python perform different actions depending on whether a specific condition evaluates to true or false. Conditional Statements are handled by if-elif-else statements and MATCH-CASE statements in Python.
- article Conditional Statements in Python
- article Python Conditional Statements
- article How to Use a Match Statement in Python
◇Loops
Loops are used to execute a block of code repeatedly.
- article Loops in Python
- article Python “while” Loops (Indefinite Iteration)
- article Python “for” Loops (Definite Iteration)
- video Python For Loops
◇Type Casting
The process of converting the value of one data type (integer, string, float, etc.) to another data type is called type conversion. Python has two types of type conversion: Implicit and Explicit.
- article Type Conversion and Casting
◇Exceptions
Python exceptions are events that occur during the execution of a program and disrupt the normal flow of the program’s instructions. When an exception is raised, it indicates that an error has occurred. Python provides a way to handle these exceptions using try-except blocks, allowing developers to manage errors gracefully and ensure the program can continue or exit smoothly.
- official Exceptions Documentation
- article Python Exceptions: An Introduction
- article Errors and Exceptions
- article Python Exception Handling
- video Exception Handling in Python
◇Functions, Builtin Functions
-
Functions In programming, a function is a reusable block of code that executes a certain functionality when it is called. Functions are integral parts of every programming language because they help make your code more modular and reusable. In Python, we define a function with the def keyword, then write the function identifier (name) followed by parentheses and a colon.
-
Example
def greet(name): print(f"Hello, {name}!") greet("World")
-
official Built-in Functions in Python
-
article Python Functions - W3Schools
-
article Defining Python Functions
◇Lists, Tuples, Sets, and Dictionaries
-
Lists: A list is just like dynamic sized arrays, declared in other languages (vector in C++ and ArrayList in Java). Lists need not be homogeneous always which makes it the most powerful tool in Python.
-
Tuple: A Tuple is a collection of Python objects separated by commas. In some ways, a tuple is similar to a list in terms of indexing, nested objects, and repetition but a tuple is immutable, unlike lists that are mutable.
-
Set: A Set is an unordered collection data type that is iterable, mutable, and has no duplicate elements. Python’s set class represents the mathematical notion of a set.
-
Dictionary: In python, Dictionary is an ordered (since Py 3.7) [unordered (Py 3.6 & prior)] collection of data values, used to store data values like a map, which, unlike other Data Types that hold only a single value as an element, Dictionary holds key:value pair. Key-value is provided in the dictionary to make it more optimized.
-
article Python for Beginners: Lists
-
video Difference Between List, Tuple, Set and Dictionary in Python
◇Tuples
Tuples are immutable sequences, meaning that once a tuple is created, its elements cannot be changed. Tuples are often used to store related pieces of information. They are defined by placing the elements inside parentheses () separated by commas.
- official Tuples Documentation
- article When and How to Use Tuples
- article Python’s tuple Data Type: A Deep Dive With Examples
- video why are Tuples even a thing?
◇Sets
Python Set is an unordered collection of data types that is iterable, mutable, and has no duplicate elements. The order of elements in a set is undefined though it may consist of various elements. The major advantage of using a set, as opposed to a list, is that it has a highly optimized method for checking whether a specific element is contained in the set.
- article An In-Depth Guide to Working with Python Sets
- article An W3Schools - Python Sets
- video Python Sets tutorial for Beginners
◇Dictionaries
In Python, a dictionary is a built-in data type that allows you to store key-value pairs. Each key in the dictionary is unique, and each key is associated with a value. Starting from Python 3.7, dictionaries maintain the order of items as they were added.
- official Dictionaries in Python
- article W3 Schools - Dictionaries
- article Dictionaries in Python
2. Data Structures & Algorithms
A data structure is a named location that can be used to store and organize data. And, an algorithm is a collection of steps to solve a particular problem. Learning data structures and algorithms allow us to write efficient and optimized computer programs.
- roadmap Visit Dedicated DSA Roadmap
- article Learn DS & Algorithms
- video Data Structures Illustrated
- feed Explore top posts about Algorithms
◇Arrays and Linked Lists
Arrays store elements in contiguous memory locations, resulting in easily calculable addresses for the elements stored and this allows faster access to an element at a specific index. Linked lists are less rigid in their storage structure and elements are usually not stored in contiguous locations, hence they need to be stored with additional tags giving a reference to the next element. This difference in the data storage scheme decides which data structure would be more suitable for a given situation.
- article Arrays in Python
- article Linked List Python
- video Array Data Structure | Illustrated Data Structures
- video Linked List Data Structure | Illustrated Data Structures
◇Hash Tables
Hash Table, Map, HashMap, Dictionary or Associative are all the names of the same data structure. It is a data structure that implements a set abstract data type, a structure that can map keys to values.
- article Build a Hash Table in Python
- article Hash Tables and Hashmaps in Python
- video Hash Table Data Structure | Illustrated Data Structures
◇Heaps, Stacks and Queues
-
Stacks: Operations are performed LIFO (last in, first out), which means that the last element added will be the first one removed. A stack can be implemented using an array or a linked list. If the stack runs out of memory, it’s called a stack overflow.
-
Queue: Operations are performed FIFO (first in, first out), which means that the first element added will be the first one removed. A queue can be implemented using an array.
-
Heap: A tree-based data structure in which the value of a parent node is ordered in a certain way with respect to the value of its child node(s). A heap can be either a min heap (the value of a parent node is less than or equal to the value of its children) or a max heap (the value of a parent node is greater than or equal to the value of its children).
-
article Heaps, Stacks, Queues
-
article How to Implement Python Stack?
-
article Python Stacks, Queues, and Priority Queues in Practice
-
article Heap Implementation in Python
◇Binary Search Tree
A binary search tree, also called an ordered or sorted binary tree, is a rooted binary tree data structure with the key of each internal node being greater than all the keys in the respective node’s left subtree and less than the ones in its right subtree.
- article How to Implement Binary Search Tree in Python
- article Binary Search Tree in Python
- video Tree Data Structure | Illustrated Data Structures
◇Recursion
Recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code.
◇Sorting Algorithms
Sorting refers to arranging data in a particular format. Sorting algorithm specifies the way to arrange data in a particular order. Most common orders are in numerical or lexicographical order. The importance of sorting lies in the fact that data searching can be optimized to a very high level, if data is stored in a sorted manner.
- article Sorting Algorithms in Python
- article Python - Sorting Algorithms
- feed Explore top posts about Algorithms
3. Modules
Modules refer to a file containing Python statements and definitions. A file containing Python code, for example: example.py
, is called a module, and its module name would be example. We use modules to break down large programs into small manageable and organized files. Furthermore, modules provide reusability of code.
- official Python Modules
- article Modules in Python
◇Builtin Modules
Python has a rich standard library of built-in modules that provide a wide range of functionality. Some of the most commonly used built-in modules include: sys, os, math, datetime, random, re, itertools, etc.
- official Python Module Index
- article Python Modules
- article Python - Built-In Modules
◇Custom Modules
Modules refer to a file containing Python statements and definitions. A file containing Python code, for example: example.py
, is called a module, and its module name would be example. We use modules to break down large programs into small manageable and organized files. Furthermore, modules provide reusability of code.
- official Python Modules
- article Modules in Python
- article Python Modules and Packages
4. Lambdas
Python Lambda Functions are anonymous function means that the function is without a name. As we already know that the def keyword is used to define a normal function in Python. Similarly, the lambda keyword is used to define an anonymous function in Python.
- article Lambdas in Python
- article How to use Lambda functions
- video Python Lambda Functions
5. Decorators
Decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure. Decorators are usually called before the definition of a function you want to decorate.
- article Learn Decorators in Python
- article Python Decorators
- video Decorators in Python
- video Python Decorators in 1 Minute
6. Iterators
An iterator is an object that contains a countable number of values. An iterator is an object that can be iterated upon, meaning that you can traverse through all the values. Technically, in Python, an iterator is an object which implements the iterator protocol, which consist of the methods iter() and next() .
- article Iterators in Python
- article Python Iterators
- article Iterators and Iterables in Python
7. Regular Expressions
A regular expression is a sequence of characters that specifies a search pattern in text. Usually such patterns are used by string-searching algorithms for “find” or “find and replace” operations on strings, or for input validation.
- official Regular Expressions in Python
- article Python Regular Expressions
- article Python - Regular Expressions
8. Object Oriented Programming
In Python, object-oriented Programming (OOPs) is a programming paradigm that uses objects and classes in programming. It aims to implement real-world entities like inheritance, polymorphism, encapsulation, etc., in programming. The main concept of OOPs is to bind the data and the functions that work on that together as a single unit so that no other part of the code can access this data.
- article Object Oriented Programming in Python
- ivideo Object Oriented Programming (OOP) In Python - Beginner Crash Course
- video OOP in Python One Shot
- video Python OOP Tutorial
◇Classes
A class is a user-defined blueprint or prototype from which objects are created. Classes provide a means of bundling data and functionality together. Creating a new class creates a new type of object, allowing new instances of that type to be made. Each class instance can have attributes attached to it for maintaining its state. Class instances can also have methods (defined by their class) for modifying their state.
- official Classes in Python
- article Python Classes and Objects
- video Python OOP Tutorial
◇Inheritance
Inheritance is a fundamental concept in object-oriented programming (OOP) that allows one class to inherit the properties and behavior of another class.
- article Python Inheritance
- article Inheritance in Python
◇Methods, Dunder
A method in python is somewhat similar to a function, except it is associated with object/classes. Methods in python are very similar to functions except for two major differences.
- The method is implicitly used for an object for which it is called.
- The method is accessible to data that is contained within the class.
Dunder or magic methods in Python are the methods that have two prefix and suffix underscores in the method name. Dunder here means “Double Under (Underscores)”. These are commonly used for operator overloading. Few examples for magic methods are: __init__
, __add__
, __len__
, __repr__
etc.
- article Method vs Function in Python
- article Python - Magic or Dunder Methods
9. Paceage Managers
Package managers allow you to manage the dependencies (external code written by you or someone else) that your project needs to work correctly.
PyPI
and Pip
are the most common contenders but there are some other options available as well.
- OpenSource pypa/pipx
- feed Explore top posts about Python
◇Poetry
Poetry is a dependency management and packaging tool for Python that runs on Windows, macOS, and Linux. Poetry efficiently installs, manages, and updates packages and their dependencies. Poetry seamlessly creates, saves, loads, and switches between project environments on your local computer. It is designed specifically for Python projects, providing a streamlined workflow for managing dependencies, virtual environments, and building packages.
Poetry as a package manager helps you find and install packages. If you need a specific version of a package or a different version of Python, Poetry handles both dependency management and virtual environments effortlessly. With just a few commands, you can set up a completely isolated environment to run a different version of Python or package configuration, while maintaining your usual development environment. Poetry’s lock file ensures consistent installs across different environments, enhancing reproducibility and stability of your projects.
- official Poetry Docs
◇Conda
Conda is an open source package management system and environment management system that runs on Windows, macOS, and Linux. Conda quickly installs, runs and updates packages and their dependencies. Conda easily creates, saves, loads and switches between environments on your local computer. It was created for Python programs, but it can package and distribute software for any language.
- official Conda Documentation
◇uv
uv is an “extremely fast” python package installer and resolver.
- OpenSource astral-sh/uv
◇PyPI
PyPI, typically pronounced pie-pee-eye, is a repository containing several hundred thousand packages. These range from trivial Hello, World implementations to advanced deep learning libraries.
- official PyPI Website
- article How to Publish an Open-Source Python Package to PyPI
- video Getting Started with Pip and PyPI in Python
- feed Explore top posts about Python
◇Pip
The standard package manager for Python is pip. It allows you to install and manage packages that aren’t part of the Python standard library.
- official pip Documentation
- article Using Pythons pip to Manage Your Projects Dependencies
- article Python PIP Introduction
- feed Explore top posts about PIP
10. Common Packages
Python has a rich ecosystem of packages and modules that can be used to get the most out of the language. A package is essentially a directory that contains multiple modules and subpackages. A module is a single file that contains a collection of related functions, classes, and variables. Modules are the basic building blocks of Python code organization. A module can be thought of as a container that holds a set of related code.
- official requests
- official pathlib
- official asyncio
- official dataclasses
- official python-dotenv
- official numpy
- iofficial pandas
◇Configuration: pyproject.toml
This file is used to define the project configuration and dependencies. It is a configuration file that contains metadata about the project, such as its name, version, dependencies, and build settings. The pyproject.toml
file is used by tools like poetry
and flit
to manage Python projects and their dependencies.
official Writing pyproject.toml files
11. List Comprehensions
List comprehensions are a concise way to create a list using a single line of code in Python. They are a powerful tool for creating and manipulating lists, and they can be used to simplify and shorten code.
- official Python List Comprehensions
- article Python - List Comprehension
- article What Exactly are List Comprehensions in Python? - CodeGuage
- article Python List Comprehensions Quiz - CodeGuage
12. Generator Expressions
Generator expressions are a concise way to create a generator using a single line of code in Python. They are similar to list comprehensions, but instead of creating a list, they create a generator object that produces the values on-demand, as they are needed. Generator expressions are a useful tool for efficiently producing large sequence of values, as they allow you to create the generator without creating the entire sequence in memory at once. This tends to use less memory, especially for large sequences.
- article Python Generator Expressions
- article List Comprehensions in Python and Generator Expressions
13. Paradigms
Python is a multi-paradigm programming language, which means that it supports several programming paradigms. Some of the main paradigms supported by Python are:
-
Imperative programming: This paradigm focuses on telling the computer what to do, step by step. Python supports imperative programming with features such as variables, loops, and control structures.
-
Object-oriented programming (OOP): This paradigm is based on the idea of objects and their interactions. Python supports OOP with features such as classes, inheritance, and polymorphism.
-
Functional programming: This paradigm is based on the idea of functions as first-class citizens, and it emphasizes the use of pure functions and immutable data. Python supports functional programming with features such as higher-order functions, lambda expressions, and generators.
-
Aspect-oriented programming: This paradigm is based on the idea of separating cross-cutting concerns from the main functionality of a program. Python does not have built-in support for aspect-oriented programming, but it can be achieved using libraries or language extensions.
-
article Python Paradigms
14. Context Manager
Context Managers are a construct in Python that allows you to set up context for a block of code, and then automatically clean up or release resources when the block is exited. It is most commonly used with the with
statement.
- official Context Libraries
- article Context Managers in Python
- article Context Managers
15. Python Frameworks
Frameworks automate the common implementation of common solutions which gives the flexibility to the users to focus on the application logic instead of the basic routine processes. Frameworks make the life of web developers easier by giving them a structure for app development. They provide common patterns in a web application that are fast, reliable and easily maintainable.
◇Plotly Dash(Synchronous)
Plotly Dash is a Python framework that allows you to build analytical web applications. It’s a high-level library that enables you to create interactive, web-based data visualization dashboards without requiring extensive knowledge of web development.
- official Plotly Dash Documentation
- official 20 Minutes Tutorial
◇Pyramid(Synchronous)
Pyramid is a general, open source, web application development framework built in python. It allows python developer to create web applications with ease. Pyramid is backed by the enterprise knowledge Management System KARL (a George Soros project).
- official Pyramid Website
- official Pyramid Documentation
- article Pyramid Framework Introduction
◇gevent(Asynchronous)
gevent is a Python library that provides a high-level interface to the event loop. It is based on non-blocking IO (libevent/libev) and lightweight greenlets. Non-blocking IO means requests waiting for network IO won’t block other requests; greenlets mean we can continue to write code in synchronous style.
- official gevent Website
- OpenSource gevent/gevent
- article gevent For the Working Python Developer
◇aiohttp(Asynchronous)
aiohttp is a Python 3.5+ library that provides a simple and powerful asynchronous HTTP client and server implementation.
- official aiohttp docs
- article Creating a RESTful API with Python and aiohttp
- video Python Asyncio, Requests, Aiohttp | Make faster API Calls
◇Tornado(Asynchronous)
Tornado is a scalable, non-blocking web server and web application framework written in Python. It was developed for use by FriendFeed; the company was acquired by Facebook in 2009 and Tornado was open-sourced soon after.
- official Tornado Website
- article A Step-by-Step Tutorial on Python Tornado
- video Tornado Python Framework
◇Sanic(Asynchronous)
Sanic is a Python 3.7+ web server and web framework that’s written to go fast. It allows the usage of the async/await syntax added in Python 3.5, which makes your code non-blocking and speedy.
official Sanic Website
◇Fast API(Synchronous + Asynchronous)
FastAPI is a Web framework for developing RESTful APIs in Python. FastAPI is based on Pydantic and type hints to validate, serialize, and deserialize data and automatically auto-generate OpenAPI documents.
- official FastAPI Documentation
- video Create an API with Fast-API (Full 19 Hour Course)
- feed Explore top posts about FastAPI
◇Django(Synchronous + Asynchronous)
Django is a free and open-source, Python-based web framework that follows the model–template–views architectural pattern. It is maintained by the Django Software Foundation, an independent organization established in the US as a 501 non-profit.
- official Django Website
- official Getting Started
- article Is Django Synchronous or Asynchronous?
- video Python Django Tutorial for Beginners
- feed Explore top posts about Django
◇Flask(Synchronous + Asynchronous)
Flask is a micro web framework written in Python. It is classified as a microframework because it does not require particular tools or libraries. It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions. Instead, it provides flexibility by requiring you to choose and integrate the best libraries for your project’s needs.
- official Flask Website
- official Flask Tutorial
- feed Explore top posts about Flask
16. Concurrency
Concurrency in Python allows multiple tasks to be executed simultaneously using different approaches. GIL (Global Interpreter Lock) limits thread execution, making multithreading less efficient for computational tasks, but suitable for I/O. Multiprocessing, using the multiprocessing module, allows multiple cores to be utilized, providing true parallelism. Asynchrony via asyncio is optimal for I/O operations, allowing thousands of connections to be processed simultaneously without blocking. The choice of approach depends on the nature of the task.
- official Concurrent Execution
- article Python Concurrency
◇Multiprocessing
Multiprocessing utilizes multiple processes, each with its own GIL. This allows full utilization of multiple processor cores, which is effective for computationally intensive tasks. Python’s multiprocessing module supports creating processes and exchanging data between them.
- official Python Documentation
- article Multiprocessing in Python with Example
- article Multiprocessing in Python
◇Asynchrony
Asynchronous programming, supported by asyncio, allows code to be executed without blocking, using async and await. This is especially useful for I/O tasks such as networking or file manipulation, allowing thousands of connections to be handled without blocking the main thread.
- official Python AsyncIO library
- article Async IO in Python: A Complete Walkthrough
◇GIL
GIL is a mechanism that allows only one thread to execute Python code at a time. This limitation is related to memory management in CPython and can reduce the efficiency of multithreaded applications on multi-core systems.
- article What is GIL?
◇Threading
Multithreading allows multiple threads within a single process. However, because of GIL, threads cannot run in parallel on different cores, which makes multithreading suitable for I/O tasks (e.g., network requests) but not for computational tasks.
- official Python Threading Library
- article Introduction to Threading in Python
17. Environments
◇Pipenv
Pipeline Environment (pipenv) is a tool that aims to bring the best of all packaging worlds (bundled, requirements.txt, setup.py, setup.cfg, etc.) to the Python world. It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your Pipfile as you install/uninstall packages. It also generates the ever-important Pipfile.lock, which is used to produce deterministic builds.
- official Pipenv Documentation
◇virtualenv
virtualenv
is a tool to create isolated Python environments. It creates a folder which contains all the necessary executables to use the packages that a Python project would need.
- official Virtual Environments
◇pyenv
pyenv is a tool for managing multiple versions of the Python programming language on Unix-like systems. It works by setting environment variables to point to the directory where the desired version of Python is installed. This allows you to switch between different versions of Python without having to modify your system’s default Python installation.
- OpenSource pyenv/pyenv
18. Static Typing
Static typing can be a powerful tool to help you catch bugs before they happen. It can also help you understand the code you’re working with, and make it easier to maintain and refactor.
- official Static Typing in Python
◇Pydantic
Pydantic is a python library for data validation and settings management using python type annotations.
- official Pydantic Documentation
◇pyre
pyre is a static type checker for Python. It is a tool that helps you find type errors in your Python code. Pyre is designed to be fast, scalable, and easy to use. It is used at Facebook to help developers catch type errors before they make it to production.
- official pyre Documentation
◇pyright
pyright is a static type checker for Python. It is a Microsoft product and is written in TypeScript. It is a language server that uses the Language Server Protocol (LSP) to communicate with the editor. It is a good alternative to mypy and pytype.
- official Pyright Documentation
◇mypy
mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or “duck”) typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking. Mypy type checks standard Python programs; run them using any Python VM with basically no runtime overhead.
- official mypy documentation
- OpenSource python/mypy
◇typing
Typing is a module in Python that provides runtime support for type hints. The typing module defines a standard set of names that can be used to describe types in the Python language. The typing module was added to the standard library in Python 3.5.
- official Typing Module
19. Code Formatting
Python code formatting is crucial for maintaining readability, consistency, and reducing errors. Black is a code formatter for Python. It is a tool that automatically formats Python code to adhere to the PEP 8 style guide. It is a great tool to use in your Python projects to ensure that your code is formatted consistently and correctly.
- official Pylint for Python
- official Black Documentation
◇yapf
yapf is a formatter for Python files. It is a tool that automatically formats Python code to conform to the PEP 8 style guide. It is similar to black but has more configuration options.
- OpenSource google/yapf
◇black
black is a code formatter for Python. It is a tool that automatically formats Python code to adhere to the PEP 8 style guide. It is a great tool to use in your Python projects to ensure that your code is formatted consistently and correctly.
- official Getting Started with Black
- official Black Documentation
◇ruff
An extremely fast Python linter and code formatter, written in Rust.
- official Ruff documentation
20. Documentation
◇Sphinx
Sphinx is a tool that makes it easy to create intelligent and beautiful documentation, written by Georg Brandl and licensed under the BSD license.
- official Sphinx Website
21. Testing
Testing in programming means checking if your code works as expected. It’s a systematic way to find and fix errors (bugs) before your code goes live. Imagine building a beautiful house without checking if the walls are straight or the roof doesn’t leak—that’s what coding without testing can feel like!
- official Unit Testing in Python
- article Python Testing Tutorial
◇tox
Tox is a tool for automating test environment management and testing against multiple interpreter configurations. It is particularly useful for Python codebase that need to support multiple versions of Python.
- official Tox Documentation
◇nose
Nose is another opensource testing framework that extends unittest
to provide a more flexible testing framework. Note that Nose is no longer maintained and pytest
is considered the replacement.
- official Introduction to Nose
- article Getting Started With Nose In Python
◇unittest / pyUnit
PyUnit is an easy way to create unit testing programs and UnitTests with Python. (Note that docs.python.org uses the name “unittest”, which is also the module name.)
- official PyUnit Docs
- article How To Use unittest to Write a Test Case for a Function in Python
- article A Gentle Introduction to Unit Testing in Python
◇doctest
Python’s standard library comes equipped with a test framework module called doctest. The doctest module programmatically searches Python code for pieces of text within comments that look like interactive Python sessions. Then, the module executes those sessions to confirm that the code referenced by a doctest runs as expected.
- official Doctest Module
- article How To Write Doctests in Python
◇pytest
pytest is a mature full-featured Python testing tool that helps you write better programs.
- official Pytest Docs
- article Pytest Tutorial
- article Effective Python Testing With Pytest
- feed Explore top posts about Python