-2

I was coding a class and a teammate did a peculiar thing:

class Dog:

    def __init__(self, hunger, size, cute):
        self.__hunger = hunger
        self.__size = size
        self.__cute = cute

    def __str__(self):
        data_1 = self.__hunger.__str__() # Why is this allowed?
        data_2 = self.__size.__str__()
        data_3 = self.__cute.__str__()
        return f"The dog is {data_1} and {data_2} but is also {data_3}"

a = Dog(20, 120, True)
print(a)

He assigned an attribute with .__ str __(). Instead of just:

    def __str__(self):
        data_1 = str(self.__hunger)
        data_2 = str(self.__size)
        data_3 = str(self.__cute)
        return f"The dog is {data_1} and {data_2} but is also {data_3}"

Why is .__ str __ allowed? and in what does it differ from the "normal" approach of just using str()?

  • 3
    Why wouldn't it be allowed? – bool3max Feb 28 '23 at 09:11
  • I would recommend you to watch a tutorial about `magic method` in python – Yanni2 Feb 28 '23 at 09:13
  • 1
    As [this answer](https://stackoverflow.com/a/41168971/12575557) explains both options are not exactly the same. – Jorge Luis Feb 28 '23 at 09:13
  • Just to say that actually the explicit conversion to `str` - one way or the other is redundant, because f-string will do that for you in any case. – buran Feb 28 '23 at 09:19
  • 1
    And to address the question in the title - _Why can an atribute have a .__str__()?_ - in python everything is object, so why not? – buran Feb 28 '23 at 09:20

1 Answers1

3

str(x) very simply calls x.__str__().

So, the usages are the same.

The recommended practice is to use str(x), however.

Very rarely is it correct to directly invoke the special dunder ( __xxx__ ) functions.

Joshua Fox
  • 18,704
  • 23
  • 87
  • 147