Python Decorators

❓ Your functions work, but now you want to add logging to them. Do you edit each function?

🎯 A decorator makes this easier: wrap a function and add logic before and after the original call.

⚙️ In this decorator example we create and use our '@log_call' to log each call with arguments and return value.

🔎 Here 𝗺𝗲𝗺𝗼𝗿𝘆_𝗴𝗿𝗮𝗽𝗵 shows how a decorator gets evaluated step by step for better understanding.

Useful decorators from Python’s standard library include:

  • @functools.cache — Cache results to avoid recomputing calls with the same arguments.
  • @functools.lru_cache — Cache results with a configurable limit, discarding the least recently used entries.
  • @functools.wraps — Preserve the original function’s name, documentation, and other metadata when writing a wrapper.
  • @functools.singledispatch — Choose an implementation based on the type of the first argument.

Other common custom decorators add: timing, retries, conversion, authentication, validation, ...

See other memory_graph visualizations.

u/Sea-Ad7805 — 23 days ago

¿Cómo convertimos, por ejemplo, 24,72 € en monedas? 🪙🪙💰⛀⛁

Este clásico ejercicio de programación para principiantes utiliza un algoritmo voraz. Pero lo interesante es que 𝐦𝐞𝐦𝐨𝐫𝐲_𝐠𝐫𝐚𝐩𝐡 nos permite ver qué ocurre en la memoria mientras se ejecuta el código.

Visualiza paso a paso el estado del programa: variables, valores, listas, diccionarios y referencias. Esto ayuda a los estudiantes a comprender y depurar su código.

Ejecuta esta demo interactiva.

¿Qué otros ejercicios de programación se beneficiarían de una visualización con memory_graph?

Consulta más visualizaciones de memory_graph.

u/Sea-Ad7805 — 27 days ago
▲ 54 r/PythonBrasil+3 crossposts

🌳 Recursive tree traversal visually explained

A binary tree can be traversed in three classic ways. The difference is simply the order in which you visit the subtrees:

  • Preorder: current node → left subtree → right subtree
  • Inorder: left subtree → current node → right subtree
  • Postorder: left subtree → right subtree → current node

This interactive memory_graph example visualizes each traversal method step by step: Binary Tree Traversal

Also see other memory_graph visualizations.

u/Sea-Ad7805 — 1 month ago

Como funciona a Avaliação Preguiçosa em Python?

No post da semana passada, mostramos que um laço for em Python funciona por meio do Protocolo de Iteração.

Esse mesmo protocolo também permite que valores sejam produzidos de forma preguiçosa.

Neste novo Exemplo de Avaliação Preguiçosa, mostramos um consumidor lendo valores de cinco fontes diferentes:

  • source1: retorna antecipadamente todos os valores por meio de uma lista
  • source2: produz valores de forma preguiçosa com uma função geradora usando yield
  • source3: produz antecipadamente todos os valores com uma compreensão de lista
  • source4: produz valores de forma preguiçosa com uma expressão geradora
  • source5: produz valores de forma preguiçosa por meio do protocolo de iteração

O mesmo laço for consome as cinco fontes. As fontes antecipadas produzem todos os valores antes que o consumidor comece a processá-los. Nas fontes preguiçosas, o produtor e o consumidor se alternam:

  • produzir → consumir → produzir → consumir → …

Cada valor é produzido somente quando o laço for o solicita.

Funções geradoras e expressões geradoras são maneiras concisas e legíveis de criar iteráveis preguiçosos. A última fonte torna explícito o mecanismo subjacente:

  • iter() obtém um iterador.
  • next() solicita o próximo valor.
  • StopIteration indica que não restam valores.

Isso mostra claramente que os geradores realizam a iteração preguiçosa implementando o Protocolo de Iteração do Python.

Veja outras visualizações do 𝐦𝐞𝐦𝐨𝐫𝐲_𝐠𝐫𝐚𝐩𝐡.

u/Sea-Ad7805 — 2 months ago
▲ 36 r/datastructures+1 crossposts

How does Lazy Evalution work in Python?

In last week’s post we showed that a Python for-loop works through the Iterator Protocol.

This same protocol also enables values to be produced lazily.

In this new Lazy Evalution Example we show one sink reading values from five different sources:

  • source1: eagerly returns all values by list
  • source2: lazily by generator function using yield
  • source3: eagerly by list comprehension
  • source4: lazily by generator expression
  • source5: lazily by iterator protocol

The same for-loop consumes all five sources. The eager sources produce all values before the sink starts consuming them. In the lazy sources producer and consumer take turns:

  • produce → consume → produce → consume → …

where each value is produced only when the for-loop requests it.

Generator functions and generator expressions are concise, readable ways to create lazy iterables. The final source makes their underlying mechanism explicit:

  • iter() obtains an iterator.
  • next() requests the next value.
  • StopIteration signals that no values remain.

This clearly shows that generators achieve lazy iteration by implementing Python’s Iterator Protocol.

See other 𝐦𝐞𝐦𝐨𝐫𝐲_𝐠𝐫𝐚𝐩𝐡 visualizations.

u/Sea-Ad7805 — 2 months ago
▲ 47 r/PythonBrasil+3 crossposts

How do Python for-loops work?

What actually happens when Python executes a for-loop?

for value in container:
    print(value)

Behind the scenes, Python uses the iterator protocol:

iterator = iter(container)
while True: 
    try: 
        value = next(iterator)
        print(value)
    except StopIteration:
        break
  • iter(container): creates an iterator.
  • next(iterator): retrieves one value at a time.

When there are no more values, the iterator raises StopIteration. The for-loop catches this exception automatically and ends the loop.

For containers that support backward iteration, Python also provides:

  • reversed(container): creates a backward iterator.

We can support these operations in our own classes by implementing:

__iter__()
__reversed__()
__next__()

This provides a powerful abstraction: an algorithm can process values without needing to know how a container stores them internally. The same algorithm can therefore work with lists, sets, dictionaries, linked lists, trees, and many other containers.

Here's an example that uses 𝐦𝐞𝐦𝐨𝐫𝐲_𝐠𝐫𝐚𝐩𝐡 to show the use of iterators on a Linked_List making the invisible mechanics of iteration visible for easy understanding.

more memory_graph examples

u/Sea-Ad7805 — 2 months ago
▲ 11 r/pygame+1 crossposts

Cupta serpant added by Tony

Tony added the Cupta unit, a serpent of dark magic who returned from the caverns and tries to siphon your life essence, with this git commit.

Tony also changed the control of player's direction from keyboard to mouse, making the player easier to control. But, this now only works when the mouse pointer is inside the game window. If it's outside the direction is still controlled by keyboard as before. So you can now choose the direction control that you prefer.

See the PythonLearningGame repo to add your own game elements to this collaborative project, or simply tell us what you would like to see added to the game.

previous PythonLearningGame post

u/Sea-Ad7805 — 2 months ago

New Putler unit added by Anonymous-Me-Me-Me

Anonymous-Me-Me-Me added a new Putler unit with this git commit and message:

Putler unit added, any likeness to real people is completely coincidental. It wants you to sign its contract, but if you get too close it tries to run to its bunker. Best to zero it before it goes into history for destroying an "empire".

We did had to add sunglasses for copyright and identity protection reasons.

PythonLearningGame is a collaborative Python project for fun and educational purposes. To add your own game elements see the PythonLearningGame repo.

previous PythonLearningGame post

u/Sea-Ad7805 — 2 months ago

Adding objects to set or dictionary: equality and hashing

An exercise to help build the right mental model for Python data.

# Output of this Python Program?
def main():
    o1, o2 = MyClass(1), MyClass(1)
    myset = {o1}
    print(o2 in myset, end=' ')
    o1.set_value(1000)
    print(o1 in myset, end=' ')

class MyClass:
    def __init__(self, v):
        self.v = v
    def set_value(self, v):
        self.v = v

main()

class MyClass:
    def __init__(self, v):
        self.v = v
    def set_value(self, v):
        self.v = v
    def __eq__(self, other):
        return self.v == other.v
    def __hash__(self):
        return hash(self.v)

main()

# --- possible answers ---
# A) TypeError: unhashable type: 'MyClass'
# B) True False False False
# C) True False False True
# E) False True True True
# D) False True True False
# See "Solution" for correct answer.
  • Solution
  • More exercises
  • Explanation: "User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)."
reddit.com
u/Sea-Ad7805 — 2 months ago

Adicionando objetos a um conjunto ou dicionário: igualdade e hashing

Um exercício para ajudar a construir o modelo mental correto sobre os dados em Python.

  • Solução
  • Mais exercícios
  • Explicação: "User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)."
u/Sea-Ad7805 — 2 months ago

Adding objects to set or dictionary: equality and hashing

An exercise to help build the right mental model for Python data.

# Output of this Python Program?
def main():
    o1, o2 = MyClass(1), MyClass(1)
    myset = {o1}
    print(o2 in myset, end=' ')
    o1.set_value(1000)
    print(o1 in myset, end=' ')

class MyClass:
    def __init__(self, v):
        self.v = v
    def set_value(self, v):
        self.v = v

main()

class MyClass:
    def __init__(self, v):
        self.v = v
    def set_value(self, v):
        self.v = v
    def __eq__(self, other):
        return self.v == other.v
    def __hash__(self):
        return hash(self.v)

main()

# --- possible answers ---
# A) TypeError: unhashable type: 'MyClass'
# B) True False False False
# C) True False False True
# E) False True True True
# D) False True True False
# See "Solution" for correct answer.
  • Solution
  • More exercises
  • Explanation: "User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)."
reddit.com
u/Sea-Ad7805 — 2 months ago

Adding objects to set or dictionary: equality and hashing

An exercise to help build the right mental model for Python data.

  • Solution
  • More exercises
  • Explanation: "User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)."
u/Sea-Ad7805 — 2 months ago
▲ 48 r/pygame+1 crossposts

Battle Tail, show what you can do

A Battle Tail is added with this git commit.

PythonLearningGame is a collaborative Python project using PyGame, just for fun and purely educational. We are looking for collaborators.

Surely some of you think you are pretty good with Python, then this is your chance to show us what you can really do besides writing know-it-all comments. Maybe add:

  • health pickups
  • shield
  • laser weapon
  • lock-on missiles
  • mines to drop
  • units shooting back
  • ...

See the PythonLearningGame repo for instructions.

previous PythonLearningGame post

u/Sea-Ad7805 — 2 months ago
▲ 841 r/pycharm+6 crossposts

Teaching Python the right way

Programming courses often focus heavily on understanding code, while paying far less attention to understanding the program state. But code does not exist in isolation. Its main goal is to change the program state, before ultimately producing some output.

To develop an accurate mental model of program execution, students need to understand both:

  • the instructions being executed
  • the values, references, and data structures those instructions create and modify

Reading code alone does not always reveal how the program state changes during execution. That is why I created 𝗺𝗲𝗺𝗼𝗿𝘆_𝗴𝗿𝗮𝗽𝗵: a tool that visualizes the state of a Python program as it changes, step by step.

It can help explain a wide range of introductory Python topics. Here are just a few examples:

Instead of reconstructing the program state from print statements, students can now watch it change as each line executes. This makes unfamiliar concepts easier to understand and bugs easier to fix.

Help your students learn Python programming more thoroughly and easily.

See: more examples

u/EmadFahim134 — 2 months ago