Не удается получить реализацию метода __repr __ () в python - PullRequest
3 голосов
/ 24 октября 2019

Я читал знаменитую книгу по питону под названием «Питонская поваренная книга» Дэвида Бизли и Брайана К. Джонса. В своей главе «Классы и объекты» они написали следующий код:

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __repr__(self):
        return 'Point({0.x!r}, {0.y!r})'.format(self)
    def __str__(self):
        return '({0.x!s}, {0.y!s})'.format(self)

Теперь только я понял, что метод repr () используется для представления объектадля разработчика и str () для слепого пользователя. Но в обоих методах, что происходит после «возврата»? В обоих случаях наверняка есть кортежи. Но какой член есть у кортежей? Я не видел ничего подобного раньше.

Ответы [ 3 ]

2 голосов
/ 24 октября 2019

И __repr__, и __str__ в вашем примере возвращают отформатированные строки, а не кортежи. Эти функции вызываются, когда к объекту вызывается repr() или str(), явно или неявно.

Например, print(Point(1,2)) напечатает результат __str__, потому что он вызывает str()внутри объекта, но print([Point(1,2)]) вместо этого выведет результат __repr__.

Для ваших собственных объектов эти методы могут возвращать все, что вы захотите, лишь бы это были только строки.

1 голос
/ 24 октября 2019

Вот разбивка определенного синтаксиса форматирования . С помощью метода str.format вы можете заполнить заполнители в данном экземпляре строки в форме {...}. Они работают с позиционными аргументами следующим образом:

>>> '{}:{}'.format(1, 2)
'1:2'
>>> '{0}:{1}'.format(1, 2)
'1:2'
>>> '{1}:{0}'.format(1, 2)
'2:1'

Это означает, что вы можете указать номер позиционного аргумента внутри фигурных скобок. Строка может ссылаться на позиционный аргумент несколько раз:

>>> '{0}:{1}:{0}'.format(1, 2)
'1:2:1'

Использование нотации .x позволяет получить доступ к атрибутам этого аргумента. Например:

>>> class Test:
...     x = 1
...     y = 2
... 
>>> '{0.x}:{0.y}'.format(Test)
'1:2'

Используя !r, вы можете принудительно использовать __repr__ этого объекта вместо __str__. Например:

>>> class Test:
...     def __str__(self):
...         return '__str__'
...     def __repr__(self):
...         return '__repr__'
... 
>>> '{0}'.format(Test())
'__str__'
>>> '{0!s}'.format(Test())
'__str__'
>>> '{0!r}'.format(Test())
'__repr__'

Таким образом, объединяя всю эту информацию, мы получаем следующее:

'Point({0.x!r}, {0.y!r})'.format(self)

Здесь определена строка формата с двумя заполнителями ({0.x!r} и {0.y!r}). Они должны быть заполнены атрибутами x и y первого позиционного аргумента (напомним, что {0} будет заменен первым аргументом, поэтому {0.x} запрашивает атрибут x этого аргумента). И, наконец, !r запрашивает __repr__ этого объекта, а не __str__ (который используется по умолчанию).

То же самое относится и к методу __str__.

Кстати, синтаксис форматирования также допускает аргументы ключевых слов, и на них можно ссылаться по их имени:

>>> '{first}:{second}'.format(first=1, second=2)
'1:2'
>>> '{second}:{first}'.format(first=1, second=2)
'2:1'
0 голосов
/ 24 октября 2019

Возможно, вы захотите попробовать это в переводчике, чтобы увидеть, что происходит:

>>> class Point:
    def __init__(self, x, y):
        """Initialize self."""
        self.x, self.y = x, y
    def __repr__(self):
        """Return repr(self)."""
        return f'{type(self).__name__}({self.x!r}, {self.y!r})'
    def __str__(self):
        """Return str(self)."""
        return f'({self.x!s}, {self.y!s})'

>>> Point(1, 2) # causes implicit call to __repr__
Point(1, 2)
>>> print(_) # causes implicit call to __str__
(1, 2)
>>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...