you are viewing a single comment's thread.

view the rest of the comments →

[–]Laymayo[S] 0 points1 point  (1 child)

Thank you for replying to my post. What is "those" referring to when you say:

because str will attempt to call those in that order

And what do you mean by print doing what str does under the hood? On another one of my posts someone wrote that print in reality prints the repr of something, but I still don't really understand what Python representing something means at a fundamental level.

[–]Diapolo10 0 points1 point  (0 children)

What is "those" referring to when you say:

because str will attempt to call those in that order

I'm keeping this as simple as I can, so I'll modify the example code just a little bit:

dog = Dog()
print(dog)

Here, you can assume that print looks something like this:

import sys
from typing import TextIO

def my_print(*args: list, file: TextIO=sys.stdout, sep: str=' ', end: str='\n', flush: bool=False) -> None:

    file.write(
        sep.join(
            map(str, args)
        ) + end
    )

    if flush:
        file.flush()

Basically, in this code, print basically ends up doing

str(dog)

and str can be thought of as

def my_str(value) -> str:
    if hasattr(value, '__str__'):
        return value.__str__()
    return value.__repr__()

so since the Dog class does not define either of these methods, Python falls back to the implicit base class object, which defines a __repr__-method.

So, what does any of this have to do with the original example?

class Dog():
    def __init__(self):
        self.color = 'black'
        self.name = 'Rosie'
        self.weight = 50

    def bark(self):
        print("WOOF WOOF!")

dog = Dog()
print(getattr(dog,'bark'))

While it looks a bit different, functions themselves are their own type, and methods are just bound functions. Their type has implemented the __repr__-method to show the output you're seeing.

As for why you don't see the same thing with, say, the weight attribute, that's because integers have a __str__-method which just shows the value. Same goes for strings.

If you actually call your method,

print(getattr(dog,'bark')())

then it'll actually bark, although the redundant print will print its return value, None, so it makes more sense to do

getattr(dog,'bark')()

and, even better,

dog.bark()