I have came across a code that it is including descriptors. As I understand, __set_name__ is a method that is called when the class is created. Then, if the class is called twice I'd get two calls.
In the following snippet I would expect to get the call in __set_name__ twice, but I am getting just one call. Why this behavior?
class SharedAttribute:
def __init__(self, initial_value=None):
self.value = initial_value
self._name = None
def __get__(self, instance, owner):
if instance is None:
return self
if self.value is None:
raise AttributeError(f'{self._name} was never set')
return self.value
def __set__(self, instance, new_value):
self.value = new_value
def __set_name__(self, owner, name):
print(f'{self} was named {name} by {owner}')
self._name = name
class GitFetcher:
current_tag = SharedAttribute()
current_branch = SharedAttribute()
def __init__(self, tag, branch=None):
self.current_tag = tag
self.current_branch = branch
@property
def current_tag(self):
if self._current_tag is None:
raise AttributeError("tag was never set")
return self._current_tag
@current_tag.setter
def current_tag(self, new_tag):
self.__class__._current_tag = new_tag
def pull(self):
print(f"pulling from {self.current_tag}")
return self.current_tag
f1 = GitFetcher(0.1)
f2 = GitFetcher(0.2)
f1.current_tag = 0.3
f2.pull()
f1.pull()
During the previous execution, __set_name__ is called with current_branch, but not called with current_tag. Why this distinction? The only call is this one:
<__main__.SharedAttribute object at 0x047BACB0> was named current_branch by <class '__main__.GitFetcher'>