> For the complete documentation index, see [llms.txt](https://igor-19.gitbook.io/qa/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://igor-19.gitbook.io/qa/avtomatizaciya-testirovaniya/python/oop-v-python-vo-vsekh-podrobnostyakh/metod-__set_name__.md).

# Метод \_\_set\_name\_\_

Этот вызывается только один раз, когда создаётся дескриптор вызывается впервые (создаётся экземпляр дескриптора `x = MyDescriptor()`) и в него передаётся имя атрибута (`x`).

```python
class ValidString:
	def __set_name__(self, owner_class, propetry_name):
		print(f"owner_class: {owner_class}")
		print(f"propetry_name: {propetry_name}")

class Person:
	my_new_name = ValidString()
1234567
```

При запуске этого кода, сразу будет запущен `__set_name__()`. Сразу на этапе компиляции, даже если не создавать экземпляр класса `Person`

```python
class ValidString:
	def __set_name__(self, owner_class, propetry_name):
		self.propetry_name = propetry_name
	def __set__(self, instance, value):
		if not isinstance(value, str):
			raise ValueError(f"{self.propetry_name} must be a String, but {type(value)} was passed")
		#key = "_" + self.propetry_name
		#setattr(instance, key, value)
		# аналогичная запись
		instance.__dict__[self.propetry_name] = value

	def __get__(self, instance, owner):
		if instance is None:
			return self
		#key = "_" + self.propetry_name
		#return getattr(instance, key, None)
		# аналогичная запись
		instance.__dict__.get(self.propetry_name, None)

class Person:
	name = ValidString()
	surname = ValidString()

p = Person()
123456789101112131415161718192021222324
```

Примечательно то, что у дескриптора нет метода `__init__` - т.к. есть `__set_name__` который делает то, что нужно

```python
p.name = "Oleg"

p.__dict__
{"name": "Oleg"}
1234
```

> \[!warning] Особенность записи имен в *пространство имен* с *дескрипторами*\
> Значение `name` запишется сразу в *локальное пространство имен* экземпляра класса `p`, а не класса `Person` - это особенность работы дескриптора.

Если проделать подобное с обычным классом - `name` запишется в сам класс (если в самом классе существует `name`, она будет перезаписана):

```python
>>> class Person:
...     name = "Ivan"
...
>>> p = Person()
>>> p.name
'Ivan'
>>> p.__dict__
{}
>>> p.name = "Dima"
>>> p.name
'Dima'
>>> p.__dict__
{'name': 'Dima'}
>>> Person.name
'Ivan'
>>> Person.__dict__
mappingproxy({'__module__': '__main__', 'name': 'Ivan', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None})
1234567891011121314151617
```

Чтение имени значения и его запись происходит всегда через дескриптор, поэтому, такой проблемы в дескрипторе нет.
