2

In this code snippet, overriding the __get__ method of Book class changes what is being returned in the BookManager when calling Book.

When __get__ is override to return a dict, book_1 is a dict. While book_2 defined within the __init__ of BookManager returns an instance of Book, and not a dict.

If I comment out __get__ in class Book, then both book_1 and book_2 inside BookManager become instances of Book.

Could someone explain what is the underlying reason for this behavior?

class Book:
  def __init__(self, name):
    self.name = name

  def __get__(self, instance, owner):
    return {'name': self.name}


class BookManager:
  book_1 = Book('python') # a dict is returned

  def __init__(self, book_name):
    self.book_2 = Book(book_name) # an instance of the object is returned


class Library:
  def __init__(self):
    self.book_manager = BookManager('javascript')

Output

>> l = Library()
>> l.book_manager.book_1
{'name': 'python'}
>> l.book_manager.book_2
<__main__.Book object at 0x7f56adf11278>
Payam Mesgari
  • 953
  • 1
  • 19
  • 38
  • 1
    Also, see https://docs.python.org/3.7/howto/descriptor.html. – chepner Apr 05 '19 at 11:58
  • Thanks for the link, but I am struggling to find my answer. Depending on where an instance of `Book` is created, a different type is returned. Could you explain how does this relate to descriptor? – Payam Mesgari Apr 05 '19 at 12:16
  • `book_1` isn't an instance attribute; it's a *class* attribute. When `foo.book1` is evaluated, the result is seen to have a `__get__` method, so instead of getting back `type(foo).__dict__['book1']`, you get `type(foo).__dict__['book1'].__get__(foo, type(foo)`. The descriptor protocol doesn't apply to instance attributes. – chepner Apr 05 '19 at 12:28

0 Answers0