Как запретить удалять поля (атрибуты) класса?

Здравствуйте! <br/> Есть такой код: <br/> <pre><code class="python">class foo(BaseModel)
  • 27 февраля 2026 г. 7:00
Ответы на вопрос 2
Найдётся несколько простых способов — самый прямой и универсальный — переопределить метод __delattr__ в вашем классе. Когда кто‑то выполняет del obj.attr (или del Class.attr для атрибутов класса), Python вызывает obj.__delattr__('attr') (или метакласс.__delattr__ для удаления атрибута класса). Поэтому можно просто бросать исключение.

Примеры.

1) Запретить удаление любых атрибутов экземпляра:
```python
class Foo(BaseModel):
    def __delattr__(self, name):
        raise AttributeError("Удаление атрибутов запрещено")
```

2) Разрешить удалять только «внутренние» атрибуты (начинающиеся с "_"):
```python
class Foo(BaseModel):
    def __delattr__(self, name):
        if name.startswith("_"):
            super().__delattr__(name)   # или object.__delattr__(self, name)
        else:
            raise AttributeError("Удаление публичных атрибутов запрещено")
```

3) Разрешить удалять только некоторые поля:
```python
class Foo(BaseModel):
    _allowed_to_delete = {"temp", "cache"}

    def __delattr__(self, name):
        if name in self._allowed_to_delete:
            super().__delattr__(name)
        else:
            raise AttributeError(f"Удаление поля {name!r} запрещено")
```

4) Запретить удаление атрибутов класса (del Foo.attr) — через метакласс:
```python
class NoDelMeta(type):
    def __delattr__(cls, name):
        raise AttributeError("Удаление атрибутов класса запрещено")

class Foo(BaseModel, metaclass=NoDelMeta):
    x = 1
```

Альтернативы и замечания:
- Если хотите только запретить del для отдельных свойств, можно использовать @property без deleter: del obj.prop вызовет AttributeError.
- Для Pydantic BaseModel обычно можно безопасно переопределять __delattr__, но если вам нужно сохранить специфичную логику BaseModel — вызывайте super().__delattr__(name) там, где хотите действительно удалить.
- Помните, что прямой вызов object.__delattr__(obj, name) (если кто‑то захочет обходить защиту) может обойти ваш код, но это экзотический вариант; обычный del будет вызывать ваш __delattr__.

Если покажете конкретный код (какие поля, требуется ли разрешать удаление некоторых из них, используете ли Pydantic и т.д.), подскажу точнее.
Переопределить <code>__delattr__</code> ? <br/> <pre><code class="python">class foo:
    name: str

    def __delattr__(self, item):
        if item == "name":
            raise AttributeError(f"Нельзя удалять атрибут: '{item}'")
        #     print('что-то печатаем')
        #     pass  # или ничего не делаем
        super().__delattr__(item)


tmp = foo()
tmp.name = "test"
try:
    del tmp.name
except AttributeError as e:
    print(e)
finally:
    print(tmp.name)</code></pre> <br/> <br/> >>>Нельзя удалять атрибут: 'name' <br/> >>>test
Похожие вопросы