Intro#

This section highlights features and tools in Python that can be used independently of any specific application.

Syntax#

Syntax is set of rules that define the structure and format of valid statements and expressions in a programming language. It dictates how symbols, keywords, and operators must be arranged to create meaningful instructions for the computer. Find out more at the specific page.


Look at the following code:

from random import choice
some_symbol = lambda: choice(["\\", "|", "/"])


print("\n".join([
    ''.join([some_symbol() for i in range(50)])
    for i in range(10)
]))
||/||\||/|\/\/\/|///|/|/|\||||\/|//\\\/////\|/||\\
/|\////\||//||\|||||/|/||///|\//|\///|||\||//|/\||
\|//||//\\/\\|\\||/|/\\///\\\|\\\\\/|/|\|\||||///\
//\///\\|\/|||///|\//|\///\\/\\/|/|\\\/\\\/\\|\||\
||/\/||||/\|\|//|/|/\||\||/\|/|\|//\|/|\|||\|\/\|\
////|/\\\//\\|//|\//\//|\/////\\\\|\\/\/|/////\|\|
|\|/\|//\\/\/|///|////||\\\|\|\|//\|||/\|\|/\||\\\
\/||/\\\|\/|/|\\\|||\\/|/\/|/|\\//||/\\|\|\/|/\\||
/|\\\|\\|\/|/\/|\\|\\|/\\|||//\/\|/\/|\\\/|/|/\///
|/|////|\\/|\///\/|\///||||\|///|\\/\\\/\\||//\/|/

At this short snippet code were used:

Operators:

  1. = - Assignment operator (used in some_symbol = lambda: ...).

  2. : - Used in the lambda function definition (lambda: choice(...)).

  3. [] - List literal and list comprehension syntax (["\\", "|", "/"], [some_symbol() for i in range(50)], and [... for i in range(10)]).

  4. () - Parentheses for function calls and grouping expressions (choice(...), some_symbol(), and range(...)).

  5. . - Attribute access (used in "\n".join(...) and ''.join(...)).

  6. for - Part of the for loop in list comprehensions.

  7. in - Used in the context of the for loop within the list comprehensions.

Literals:

  1. "\\", "|", "/" - String literals representing the symbols in the list.

  2. \n - String literal for a newline character.

  3. '' - Empty string literal.

  4. 50, 10 - Integer literals used as arguments to range().

Keywords:

  1. from - Used for importing specific parts of a module (from random import choice).

  2. import - Used to bring a module or part of a module into the current namespace.

  3. lambda - Used to create an anonymous function.

  4. for - Used in the list comprehension to iterate over a range.

  5. in - Used in the for loop to iterate over elements.

Files & folders#

This section reviews options for working with files and folders in Python. There are some tools typically used in such cases:

  • os: A core Python module for interacting with the operating system.

  • pathlib: A package that provides convenient path operations in Python.

  • shutil: Implements additional tools not available in the previous modules out of the box.

Find out more in the special page.


As example really typical task - list content of the /tmp folder:

import os
os.listdir("/tmp")[:5]
['dumps',
 'pyright-11804-s2fIQ36Ehj4n',
 'snap-private-tmp',
 'steam_chrome_overlay_uid1000_spid10387',
 'systemd-private-57bd5d93c4894144aa34f82104c1dc8e-fwupd.service-wLri9E']

Packages#

Packages in Python are additional code modules that extend the standard Python library. This section provides an overview of:

  • Building packages: Transforming source code into a distributable format.

  • Installing packages: Tools and methods for managing Python packages.

  • Python indexes: Repositories for storing Python packages and the process of uploading packages to them.

Find all that staff on the particular page of this site.


The packages are usually located in the lib/python<version>/site_path directory of the Python distribution. The following cell shows the exact directory for the interpreter used to show examples.

Random entitlements from this folder will also be printed.

import os
import sys
import random
from pathlib import Path

packages_path = sys.path[-1]
print(packages_path, end="\n"*3)
for f in random.sample(os.listdir(packages_path), 10):
    print(f)
/home/fedor/Documents/knowledge/venv/lib/python3.12/site-packages


safetensors
referencing
psutil
sphinx_comments-0.0.3.dist-info
myst_nb
aiosignal
jedi-0.19.1.dist-info
jupyter_core-5.7.2.dist-info
jedi
smmap-5.0.1.dist-info

The most basic tool for working with Python packages, pip, is itself a Python package. The following cell navigates to its folder and displays the contents of its __init__.py file.

print((Path(packages_path)/"pip"/"__init__.py").read_text())
from typing import List, Optional

__version__ = "24.0"


def main(args: Optional[List[str]] = None) -> int:
    """This is an internal API only meant for use by pip's own console scripts.

    For additional details, see https://github.com/pypa/pip/issues/7498.
    """
    from pip._internal.utils.entrypoints import _wrapper

    return _wrapper(args)

Logging#

Logging is a built-in Python library for organizing logs. Its purpose is to create different Logger objects, each of which can be used in a specific part of the program, allowing you to maintain control over your program’s output.

For more details check corresponding page.


The following example demonstrates how to create a logger, show_logger, and attach different handlers to it. Handlers define the destination of the output, and each handler has a unique formatter—an object that defines the format of the records produced by the corresponding handler.

import logging

show_logger = logging.getLogger("show logger")

handler1 = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler1.setFormatter(formatter)

handler2 = logging.StreamHandler()
formatter = logging.Formatter('%(message)s|%(asctime)s|%(levelname)s')
handler2.setFormatter(formatter)

show_logger.addHandler(handler1)
show_logger.addHandler(handler2)

show_logger.critical("This is my message")
2024-08-30 11:58:58,516 - CRITICAL - This is my message
This is my message|2024-08-30 11:58:58,516|CRITICAL

In the end, we receive messages formatted according to the logger’s settings.

Data class#

There is a special tool in Python called dataclasses. Dataclasses allow you to build classes that store data and provide some built-in tools for operating with them. The crusial features are:

  • Automatically generated __init__ that will create all required attributes.

  • Converting to string as __repr__ method will be defined in dataclass.

  • Comparing as __eq__ method will be implemented.

Find out more in the special page.


To define a dataclass, you have to use the dataclasses.dataclass decorator. The following cell defines one that we’ll use:

from dataclasses import dataclass

@dataclass
class SomeData:
    value1: int
    value2: str

Any instance of such a class can be transformed into a string in the format <ClassName>(<attr1>=<val1>, ...). The following cell shows this:

print(SomeData(1, "wow"))
SomeData(value1=1, value2='wow')

You can compare dataclasses out of the box, and if their attributes have the same values, you will find that the instances are equal.

print(SomeData(1, "wow") == SomeData(1, "wow"))
print(SomeData(1, "wow") == SomeData(2, "oh my gosh"))
True
False

Functools#

Functools is a module in Python that provides functions that return other functions that have specific properties. Check corresponding documentation.

Partial#

With functools.partial you can create a function that wraps another function in order to define default values for the arguments of the wrapped function. This is really useful when you need to pass the same set of arguments many times for example in unit tests.


The following cell defines a function with three parameters and demostrates how to call it.

from functools import partial

def some_fun(a, b, c):
    print(f"{a}, {b}, {c}")

some_fun(1, 2, 3)
1, 2, 3

Now created default_some_fun function, which is the same as some_fun but uses a=3 and b=10 as default values.

default_some_fun = partial(some_fun, a=3, c=10)

The following cell shows the default_some_fun call with b set to “hello”

default_some_fun(b="hello")
3, hello, 10

Obviously it is just like some_fun(3, "hello", 10).

Note: It is possible to redefine values specified in parital. The following code calls default_some_fun with new value for a parameter.

default_some_fun(a="three", b="hello")
three, hello, 10

As a result, instead of 3 specified by partical, we get three specified in the call to the result.

Note: With partial you can redefine any callable you like not only functions, for example you can specify a class that will always have the same argument of the __init__. The following cell creates a special object that will behave just like a dict but will have a default hello: 10 key-value pair.

value = partial(dict, hello=10)
value(), value(new=3)
({'hello': 10}, {'hello': 10, 'new': 3})