Data types
- Numeric Types
- int
- float
- complex
- Sequence Types
- str #""
- list #[]
- tuple #()
- Mapping Type
- dict #{}
- Set Types
- set #{}
- frozenset
- Boolean Type
- bool #True/False
- Binary Types
- bytes #[]
- bytearray
- memoryview
Mutable and Imutable
Mutable data types are those whose contents can be changed after creation, while immutable data types cannot be changed once they are created.
Mutable data types:
- Lists
- Dictionaries
- Sets
- Byte arrays
Immutable data types:
- Integers (
int
) - Floating-point numbers (
float
) - Complex numbers (
complex
) - Strings (
str
) - Tuples (
tuple
) - Frozensets (
frozenset
) - Bytes (
bytes
) - Booleans (
bool
)
All mutable data type will point to same memory when they have same vaule
Example
Namespace
A namespace is a mapping from names to objects. It serves as a container for identifiers (variable names, function names, class names, etc.) and helps in avoiding naming conflicts and organizing code logically.
Local Namespace:
- A local namespace contains the names that are defined within a specific function or method.
- It is created when a function is called and is destroyed when the function exits.
- The local namespace is accessible only within the function or method where it is defined.
Enclosing Namespace (non-local):
- An enclosing namespace contains names defined in the enclosing function or outer scope.
- It is used in nested functions or closures. use keyword
non-local
Names in the enclosing namespace are accessible within the nested function but not modifiable by it.
Global Namespace:
- The global namespace contains names defined at the top level of a module or script.
- It is created when the module is imported or when the script is executed.
Built-in Namespace:
- The built-in namespace contains names of built-in functions, exceptions, and other objects provided by Python.
- It is automatically loaded when Python starts up.
- The objects in
__builtins__
include commonly used functions likeprint()
,len()
,range()
, etc - Python 3,
__builtins__
is read-only by default.
Vars
In Python, the vars()
function is used to return the __dict__
attribute of an object, which contains all the writable attributes of that object in the form of a dictionary. If you call vars()
without any arguments, it returns the __dict__
of the current local scope.
input and output
Reading Input:
The input()
function takes an optional string argument that serves as the prompt, which will be displayed to the user before waiting for input. It returns the user’s input as a string.
Output:
The print()
function is used to display output to the console. You can pass one or more objects as arguments to print()
, and they will be printed to the console separated by spaces by default.
Formatting Output:
You can also format the output using various techniques such as string formatting or using the .format()
method:
Conditional Statements:
if-elif-else
statement:
The if-elif-else
statement is used when there are multiple conditions to check.
Loops:
1. for
loop:
The for
loop is used to iterate over a sequence (such as a list, tuple, string, etc.) or any iterable object.
2. while
loop:
The while
loop is used to execute a block of code repeatedly as long as a condition is true.
Loop Control Statements:
- break
statement:
The break
statement is used to exit the loop prematurely based on a condition.
- continue
statement:
Functions
function will default return none
arbitrary positional and Arbitrary Keyword arguments
Positional : When we define a parameter with *args
, it allows the function to accept any number of positional arguments. These arguments are packed into a tuple inside the function
Keyword: it allows the function to accept any number of keyword arguments. These arguments are packed into a dictionary inside the function.
Unpacking arguments
To pass elements of a list, tuple, or dictionary as separate arguments to a function.
Lambda Functions
Lambda functions, also known as anonymous functions,
Lambda functions are typically used when you need a simple function for a short period, often as an argument to higher-order functions like map()
, filter()
, and sorted()
, or within a list comprehension.
Generators
Generators are functions that can pause and resume their execution. They generate a sequence of values lazily, one value at a time, and only when requested.
Memory Efficiency: Generators produce values on-the-fly, so they don’t store the entire sequence in memory at once. This makes them memory efficient, particularly for large datasets.
Lazy Evaluation: Values are generated only when requested, which can improve performance and reduce unnecessary computation.
Support for Infinite Sequences: Generators can produce infinite sequences of values without running out of memory or crashing the program.
Decorators
Allows us to modify or extend the behavior of functions or methods. They provide a clean and concise way to add functionality to existing code without modifying it directly.
When we give multiple decorator it will excute from bottom to top
Modules
When a Python module is imported, it gets its own __name__
attribute. This attribute contains the name of the module. Additionally, modules have a __file__
attribute, which stores the path to the module’s source file.
When Python executes a script, it assigns the special variable __name__
a value of "__main__"
if the script is being run directly. By using if __name__ == "__main__":
, we can write code that will only execute when the script is run directly and not when it’s imported as a module.
Import module resolution
sys.path: Python maintains a list of directories called sys.path
where it searches for modules when you import them. This list includes several default locations such as:
- The directory containing the script that is being executed.
- The directories listed in the
PYTHONPATH
environment variable. - The installation-dependent default path, which typically includes standard library directories, site-packages directories, etc.
site-packages Directory: When you install third-party packages using tools like pip
, they are typically installed into a directory called site-packages
. This directory contains modules and packages installed via pip
and is added to sys.path
.
Let say if we have two file inside single folder if we want to import both file like from foldername import *
it won’t work we need to use package by creating the __init__
file
Packages
A package is a collection of Python modules organized in a directory hierarchy. It typically contains an __init__.py
file to indicate that the directory should be treated as a package. Packages allow you to further organize your code into meaningful units.
Wheel files
is a built package format for Python that helps distribute and install Python software. It is a binary distribution format, which means it contains all the files necessary for running the package without requiring a build step. This format makes installation faster and easier compared to source distributions, which need to be built on the user’s system.
when we installing pkg using pip it get downloaded as wheel file.
Wheel File Structure
A wheel file is essentially a ZIP archive with a specific naming convention and structure. The structure typically includes:
data/
: Optional directory for package data files.dist-info/
: Directory containing metadata files such asMETADATA
,RECORD
,WHEEL
, andentry_points.txt
.name/
: The package’s code files.
pycache
__pycache__
is a directory automatically created by Python when it compiles source files into bytecode files. Python compiles source files into bytecode (.pyc) files to speed up execution by avoiding recompilation each time the script is run.
- When you import a module in Python, the interpreter first checks if there’s a corresponding bytecode file (.pyc) in the
__pycache__
directory. - If the bytecode file exists and is up to date (i.e., the source file has not been modified since the bytecode was generated), Python uses the bytecode file for execution, bypassing the compilation step.
- If the bytecode file does not exist or is outdated, Python compiles the source file into bytecode and stores it in the
__pycache__
directory for future use.
Context manger
objects that are used with the with
statement to ensure that certain operations are properly initialized and cleaned up
Builtin modules
Exception handling
Custom erros:
OOPS
Attributes: Attributes are variables associated with a class or an object. They represent the state of the object. methods of attributes hasattr()
, setattr()
, delattr()
and getattr()
Methods:Methods are functions defined within a class that operate on the object’s data. The first argument of a method is always self
, which refers to the object itself.
Constructor (__init__
): The __init__
method is a special method called the constructor. It is used to initialize object attributes when an object is created.
Inheritance Inheritance allows a class (subclass) to inherit attributes and methods from another class (superclass). Subclasses can override or extend the behavior of the superclass.
Class (static) variable: are variables that are shared among all instances (objects) of a class. They are defined within a class but outside of any methods. Class variables are accessed using the class name rather than instance variables
Static method : It is decorated with @staticmethod
to indicate that it is a static method. can be called using class name or using instance. static methods don’t have access to instance attributes or methods
Class Methods: They have access to class variables but not to instance variables.The first parameter of a class method conventionally named cls
, which refers to the class itself.
Dunder methods: are special methods in Python that have double underscores at the beginning and end of their names. These methods allow you to define behavior for built-in operations in Python.
File handling
File Modes
"r"
: Read mode (default). Opens a file for reading. File must exist."w"
: Write mode. Opens a file for writing. Creates a new file or truncates an existing file."a"
: Append mode. Opens a file for appending. Creates a new file if it does not exist."b"
: Binary mode. Used in conjunction with other modes to open a file in binary mode (e.g.,"rb"
,"wb"
,"ab"
).
Threading
create a new thread by subclassing the Thread
class and overriding the run()
method or by passing a target function to the Thread
constructor.
Join: join()
method is used to wait for a thread to complete its execution before continuing with the main thread. When you call join()
on a thread object, the program will block and wait until that thread finishes its execution.If we want the main thread to wait for one or more additional threads to finish their execution before proceeding further, you can call the
join() method on those thread objects.
Daemon thread: Are threads that run in the background and are automatically terminated when the program exits it not like normal threads
Byte code
Generated by the Python interpreter when it translates the source code into a form that can be executed by the Python virtual machine (PVM).
Async IO
asyncio
module provides infrastructure to write single-threaded concurrent code using coroutines, multiplexing I/O access over sockets and other resources, running network clients and servers, and other related primitives.
-
Coroutines (
async
/await
): Coroutines are special functions that can pause execution atawait
expressions and then resume where they left off. They are defined usingasync def
syntax and can be paused and resumed asynchronously. -
Event Loop: The event loop is the central component of
asyncio
. It manages and schedules coroutines, IO operations, and callbacks. The event loop continuously checks for events such as IO operations, callbacks, and scheduled tasks, and executes them in an asynchronous manner. -
Tasks: Tasks are used to schedule coroutines for execution on the event loop. A task wraps a coroutine, allowing it to be scheduled and managed by the event loop.
-
Event Loop Policies: Event loop policies allow you to customize the event loop used by
asyncio
. This can be useful for integratingasyncio
with other event loops or frameworks.
Coroutine
A coroutine is a special type of function in Python (and other programming languages) that allows you to write asynchronous code. Unlike regular functions, coroutines can pause their execution to let other code run, making them ideal for tasks that involve waiting, such as network requests or file I/O.
coroutine starts running when it is awaited or scheduled to run within an event loop.
Task
task is a wrapper for a coroutine that allows it to run concurrently with other coroutines. if we use await it wil run one by one which is same as single thread.
we can create tasks using asyncio.create_task()
or loop.create_task()
Not like gather
it will cancel other task on error
Error handling in task and gather
return_exceptions
argument to return exceptions as part of the results instead.
Nest async io
nest_asyncio
is a Python library that allows you to run an asyncio event loop within an already running event loop. This is particularly useful in environments like Jupyter notebooks or other interactive environments where an event loop may already be running.
Type hints & Annotations
Introduced in python 3.5 above it won’t force to strict type we can give any type
if we want to force type we need to use static analysis of code using pip install mypy
Other Modules
Pydantic
Pydantic is the most widely used data validation library for Python.
Docstrings
A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. It is used to document the code and provide information about what the code does, its parameters, return values, and any other relevant details.
A docstring is typically enclosed in triple quotes """..."""
or '''...'''
, and it can span multiple lines.
Package mangement
In Python, package management and package locking are handled using tools that manage dependencies and ensure consistency across environments. The main tools that provide functionality similar to package.json
and package-lock.json
in JavaScript are:
1. requirements.txt
+ pip
requirements.txt
is a simple text file used to specify the exact versions of the Python packages your project depends on.pip
is the package manager that installs and manages these packages.
To create a requirements.txt
file:
To install packages from it:
However, this setup doesn’t lock exact versions for sub-dependencies (like package-lock.json
does).
2. pipenv
Pipenv
is a modern Python packaging tool that creates two files:Pipfile
: Defines project dependencies.Pipfile.lock
: Locks the exact versions, including transitive dependencies, ensuring consistency across environments.
Commands:
- Install a package:
- Generate
Pipfile
andPipfile.lock
and install dependencies:
3. poetry
Poetry
is another modern package manager that also handles dependency management and version locking.pyproject.toml
: Similar topackage.json
, it contains dependency specifications.poetry.lock
: Similar topackage-lock.json
, it locks all package versions and their dependencies.
Commands:
- To install and manage dependencies:
- Add a package:
4. conda (for Anaconda users)
-
Conda
is a package manager for Python and other languages, typically used in scientific computing. -
environment.yml
: Similar topackage.json
, this file defines all packages and their versions, along with specific channels. -
You can export a lock file using:
Comparison:
Tool | Dependency File | Lock File | Environment Isolation | Notes |
---|---|---|---|---|
pip | requirements.txt | No Lock File | No | Most basic setup |
pipenv | Pipfile | Pipfile.lock | Yes | Modern solution |
poetry | pyproject.toml | poetry.lock | Yes | Great for projects with complex dependencies |
conda | environment.yml | No Lock File | Yes | Popular for data science projects |
new tools
- pydantic
- Ruff [ linting and formating]
- uv
- mypy