blense.
HomeFrontendCodeAINewsGuidesCheatsheetsAbout

Technology decoded, always.

A curated read on AI, product, and the culture behind the code. No noise, no hype.

blense.

Technology with focus. Stories about what innovation really changes.

Sections

FrontendArtificial IntelligenceCode & DevTech News

Blense

AboutRSSPrivacy policyTermsCookies
© 2026 Blense · blense.fun
Code & Development

Python Decorators: Understanding @property, @classmethod, and @staticmethod

Confused by Python decorators? This guide demystifies @property, @classmethod, and @staticmethod, showing you how to write cleaner, modular code.

Gby Genildo SouzaJun 196 min read
Python Decorators: Understanding @property, @classmethod, and @staticmethod
Mastering Python Decorators
  • 1Decorators are functions that wrap other functions to add behavior, serving as a powerful tool for code reuse and the DRY principle.
  • 2The @property decorator allows methods to be accessed like attributes, enabling clean syntax for data validation and encapsulation.
  • 3Use @classmethod to define factory methods that receive the class itself as an argument, providing flexible ways to instantiate objects.
  • 4The @staticmethod decorator creates utility functions within a class that do not require access to instance or class state.
  • 5Syntactic sugar with the @ symbol simplifies the application of decorators, making code more readable and easier to maintain.

Have you ever seen @property, @staticmethod and felt that look of confusion? Before understanding these three, we need to understand what a decorator is for real.


First: functions are first-class citizens

In Python, functions are objects like any other. This means you can pass functions as arguments, return functions and store functions in variables.

PYTHON
def saudacao():    print("Olá, mundo!")# Guardando a função numa variável (sem os parênteses!)minha_fn = saudacaominha_fn()  # Olá, mundo!# Passando função como argumentodef executar(fn):    print("Antes...")    fn()    print("Depois.")executar(saudacao)# Antes...# Olá, mundo!# Depois.

💡 Why does this matter? A decorator is nothing more than a function that receives another function, adds some behavior, and returns a new function. That is exactly it.


Building a decorator from scratch

Let's create a decorator that measures the execution time of any function. Useful for debugging and optimization.

PYTHON
import timedef medir_tempo(funcao):    # funcao é a função que vamos "decorar"    def wrapper(*args, **kwargs):        inicio = time.time()        resultado = funcao(*args, **kwargs)  # executa a função original        fim = time.time()        print(f"⏱️ {funcao.__name__} levou {fim - inicio:.4f}s")        return resultado    return wrapper  # retorna a função "embrulhada"# Sem a sintaxe @, seria assim:def processar_dados():    time.sleep(0.5)    print("Dados processados!")processar_dados = medir_tempo(processar_dados)  # manual e feioprocessar_dados()

🧠 Mental model: the decorator is a wrapper. The original function goes in, the decorator puts it inside a box with extra behaviors, and returns the box.

Syntactic sugar: the @

The @ is just a prettier way to write exactly what we did above. Both versions are identical:

PYTHON
# Com @ — a forma que você vai usar sempre@medir_tempodef processar_dados():    time.sleep(0.5)    print("Dados processados!")processar_dados()# Dados processados!# ⏱️ processar_dados levou 0.5003s# Funciona em qualquer função!@medir_tempodef buscar_usuario(id):    time.sleep(0.1)    return {"id": id, "nome": "Genildo"}usuario = buscar_usuario(42)# ⏱️ buscar_usuario levou 0.1001s

✨ Got the magic? You wrote the logic to measure time only once and applied it to any function with a @. This is the DRY (Don't Repeat Yourself) principle in action.


Now for real: OOP decorators

Python has three native decorators for classes that you will see everywhere:

Python Native Class Decorators
@property
Attribute-like Method

Allows methods to be accessed like attributes for controlled access.

@classmethod
Class Method

Defines methods bound to the class, not instances.

@staticmethod
Static Utility

Creates independent functions inside the class without access to instance or class.

Key decorators that shape class behavior and usage

Decorator

What it does

@property

Method that looks like an attribute

@classmethod

Class method, not object method

@staticmethod

Independent function inside the class

@property — controlled access with elegance

Remember encapsulation with __saldo in Part 1? The @property allows you to access protected data as if they were simple attributes, but with logic underneath.

@property Controlled Access to Private Attributes accessed by exposed as Private attribute __preco Holds the actual price value @property preco() method Getter and setter with logic External attribute-like access Uses preco as if attribute
@property Controlled Access to Private Attributes
PYTHON
class Produto:    def __init__(self, nome, preco):        self.nome = nome        self.__preco = preco  # privado    @property    def preco(self):        # getter: chamado ao ler produto.preco        return f"R$ {self.__preco:.2f}"    @preco.setter    def preco(self, valor):        # setter: chamado ao atribuir produto.preco = X        if valor < 0:            raise ValueError("Preço não pode ser negativo! 🚫")        self.__preco = valorcamiseta = Produto("Camiseta Blueprint", 89.90)print(camiseta.preco)    # R$ 89.90  — parece atributo, mas é método!camiseta.preco = 79.90   # usa o setter automaticamenteprint(camiseta.preco)    # R$ 79.90camiseta.preco = -10     # ValueError: Preço não pode ser negativo! 🚫

🔶 When to use @property? When you want access to data to have built-in logic — formatting, validation, derived calculation — but the external API remains clean, without get_preco() and set_preco().


@classmethod — building objects in alternative ways

A @classmethod receives the class as the first argument (conventionally cls), not the object. It is widely used to create factory methods — alternative ways to instantiate a class.

📝
@classmethod key concept

A @classmethod receives the class itself as the first argument (cls), not an instance. This allows it to access and modify class state or create new instances in alternative ways. It is commonly used for factory methods or alternative constructors, providing flexible object creation patterns.

PYTHON
class Artigo:    def __init__(self, titulo, autor, categoria):        self.titulo = titulo        self.autor = autor        self.categoria = categoria    @classmethod    def de_dicionario(cls, dados: dict):        # cria um Artigo a partir de um dict (ex: resposta de API)        return cls(            titulo=dados["title"],            autor=dados["author"],            categoria=dados["category"]        )    @classmethod    def rascunho(cls, titulo):        # cria um artigo rascunho com defaults        return cls(titulo=titulo, autor="Desconhecido", categoria="Rascunho")    def __repr__(self):        return f"[{self.categoria}] {self.titulo} — {self.autor}"# Forma normala1 = Artigo("OOP em Python", "Genildo", "Python")# Via dicionário (vindo de uma API, por exemplo)payload = {"title": "Decorators", "author": "Genildo", "category": "Python"}a2 = Artigo.de_dicionario(payload)# Rascunho rápidoa3 = Artigo.rascunho("Ideia de artigo novo")print(a2)  # [Python] Decorators — Genildoprint(a3)  # [Rascunho] Ideia de artigo novo — Desconhecido

@staticmethod — stateless utility

A @staticmethod does not receive self or cls. It is a common function that lives inside the class for logical organization, not for coupling.

📝
@staticmethod: Stateless Utility Function

@staticmethod methods do not receive self or cls parameters, meaning they do not interact with instance or class data.

They serve as utility functions grouped logically within a class, without maintaining state or coupling to class/instance.

Use @staticmethod when the method neither needs instance nor class context, clarifying its stateless role and avoiding confusion.

PYTHON
class ValidadorSenha:    @staticmethod    def tem_tamanho_minimo(senha: str) -> bool:        return len(senha) >= 8    @staticmethod    def tem_numero(senha: str) -> bool:        return any(c.isdigit() for c in senha)    @staticmethod    def validar(senha: str) -> bool:        return (            ValidadorSenha.tem_tamanho_minimo(senha) and            ValidadorSenha.tem_numero(senha)        )print(ValidadorSenha.validar("abc"))        # False — curta e sem númeroprint(ValidadorSenha.validar("blueprint1")) # True ✅

⚠️ Quick rule to avoid confusion:

  • Need to access self (object data)? → normal method

  • Need to access cls (the class itself)? → @classmethod

  • Don't need either? → @staticmethod


Custom decorator + OOP together

To wrap it up: a decorator that automatically logs every method call in a class. This pattern appears in real-world frameworks.

PYTHON
def logar_chamada(funcao):    def wrapper(*args, **kwargs):        print(f"📋 Chamando: {funcao.__name__}()")        resultado = funcao(*args, **kwargs)        print(f"✅ Concluído: {funcao.__name__}()")        return resultado    return wrapperclass ServicoDePost:    def __init__(self):        self.__posts = []    @logar_chamada    def criar_post(self, titulo):        self.__posts.append(titulo)        return titulo    @logar_chamada    def publicar_todos(self):        for post in self.__posts:            print(f"  🚀 Publicando: {post}")    @property    def total(self):        return len(self.__posts)    @staticmethod    def slug(titulo: str) -> str:        return titulo.lower().replace(" ", "-")servico = ServicoDePost()servico.criar_post("OOP em Python")servico.criar_post("Decorators em Python")servico.publicar_todos()print(f"Total: {servico.total}")print(ServicoDePost.slug("Decorators em Python"))# decorators-em-python

What you learned today

  • ✅ Functions are objects in Python — they can be passed and returned.

  • ✅ A decorator is a function that wraps another function.

  • ✅ The @ is syntactic sugar — no magic, just elegance.

  • ✅ @property creates controlled access to private attributes.

  • ✅ @classmethod operates on the class, not the object — great for factory methods.

  • ✅ @staticmethod is a utility function that lives in the class for organization.

  • ✅ Custom decorators + OOP = clean and reusable code.

The elite dev's arsenal.
Python Variables: A Practical Guide for Beginners6 minMicrofrontends with Angular and Nx: what nobody tells you15 minDebugging CSS: The Forgotten Margin and Frontend Lessons8 minCopilot CLI Becomes an Agent: Writes Code, Runs Tests, and Fixes Bugs Without Prompting3 min

Keep exploring
Want more content like this?

Check out other articles in the same vein and keep the momentum.

See more articles
#Python#Django

The elite dev's arsenal.

Microfrontends with Angular and Nx: what nobody tells you
Code & Development

Microfrontends with Angular and Nx: what nobody tells you

Most tutorials show how to build microfrontends in minutes, but few reveal the architectural debt that emerges after months of production deployments.

Genildo Souza · Jul 28 · 15 min
JavaScript Event Loop: The Heart of Non-Blocking Concurrency — Revisited in 2025
Code & Development

JavaScript Event Loop: The Heart of Non-Blocking Concurrency — Revisited in 2025

The Event Loop is not just a simple loop, but a sophisticated coordination mechanism between Call Stack, queues, and runtime. Essential for JS concurrency, it enables thousands of asynchronous operations without blocking the UI. This guide explores its structure, differences between Node.js and browsers, common bugs, advanced techniques, and 2025 trends like Structured Concurrency and scheduler.yield().

Genildo Souza · Jul 26 · 6 min
Next.js 16 PPR: Eliminate the static vs. dynamic tradeoff and achieve Edge TTFB with fresh data
Code & Development

Next.js 16 PPR: Eliminate the static vs. dynamic tradeoff and achieve Edge TTFB with fresh data

Partial Prerendering in Next.js 16 resolves the classic rendering tradeoff, delivering static speed with dynamic data in one seamless response.

Genildo Souza · Jul 13 · 14 min
In this article
  • First: functions are first-class citizens
  • Building a decorator from scratch
  • Syntactic sugar: the @
  • Now for real: OOP decorators
  • @property — controlled access with elegance
  • @classmethod — building objects in alternative ways
  • @staticmethod — stateless utility
  • Custom decorator + OOP together
  • What you learned today