Софтуерно Инженерство
Loading...
+ Нов въпрос
Milan_Popov avatar Milan_Popov 17 Точки

magic methods

Дълго търсих и не намерих обяснение, какво кара функцията print(f) да извика специалния метод  __str__ в долния код? Какво ги свързва?

class Figure:
    def __init__(self, center_x, center_y, color='black'):
        self.center_x = center_x
        self.center_y = center_y
        self.color = color

    def __str__(self):
        return "Figure - center_x={} , center_y={}, color={}".format(
            self.center_x,
            self.center_y,
            self.color
        )

f = Figure(10, 20, 'red')
print(f)


Може ли някой да ми го обясни по задълбочено. Изобщо какъв е смисъла от цялята тази гимнастика, като можеш просто да си извикаш метод който си декларирал в класа?

Тагове:
0
Python 16/08/2016 16:49:10
Wencakisa avatar Wencakisa 2 Точки

Привет!

В Python, когато извикваш функцията print() с някакъв параметър x, тя от своя страна прилага метода str() върху този x.

Пример:

  • print(2.43)
    • На конзолата се изкарва: 2.43, което всъщност е стрингът '2.43'
    • '2.43' == str(2.43)  # True

Както знаем, в Python всичко е обект. Прилагането на метода str() върху обекта x, е еквивалентно на x.__str__(). Същата функционалност има и метода __repr__

  • Линк към документацията на Python 3 за __repr__ и __str__ : http://bit.ly/2bAxkvO
  • Малко информация за __repr__ директно от Таковата:

В Python има и още един стандартен метод с подобно предназначение - __repr__ (съкращение от representation - представяне на обекта).

Обикновено __repr__ се използва за техническо представяне на обекта като string, като в него е добре да се включи цялата информация за обекта, която да помогне на програмиста да се ориентира за състоянието на обекта. Методът __str__ се използва за представяне на обекта на потребителя - обикновено той включва "човешко" форматиране на данните, локализация и други. Ако в клас е дефиниран само един от тези два метода, Python автоматично ще използва дефинираният метод, когато е необходимо.

И сега нека погледнем твоя код:

class Figure:
    def __init__(self, center_x, center_y, color='black'):
        self.center_x = center_x
        self.center_y = center_y
        self.color = color

    def __str__(self):
        return "Figure - center_x={} , center_y={}, color={}".format(
            self.center_x,
            self.center_y,
            self.color
        )

Може би е по-добре вече дефинираният метод __str__ да стане __repr__, по простата причина че " __repr__ се използва за техническо представяне на обекта като string", а стойността, която връща твоят __str__ е именно такава.

Как аз бих написал __repr__ :

def __repr__(self):

    return '{} - {}'.format(self.__class__.__name__, str(self.__dict__))

>>> f = Figure(center_x =10, center_y=20, color='green')

>>> print(f)

# Прилагане на str() върху обекта f, който е инстанция на Figure

# Нямаме дефиниран метод __str__(), затова се извиква __repr__()

# self.__class__.__name__ == името на класа, а именно Figure

# self.__dict__ == dictionary, съдържащо имената на всички полета, дефинирани в конструктора, заедно с техните стойности

Output на конзолата:

    Figure - {center_x: 10, center_y: 20, color='green'}

 

2
17/08/2016 15:39:09
Milan_Popov avatar Milan_Popov 17 Точки

Благодаря.

0
b.yordanov avatar b.yordanov 146 Точки

Разбира се, че  можеш да си дефинираш всички методи, но няма смисъл да го правиш след като някой го е дефинирал вече, пък и се получава нещо като "стандартизация" може би.

0