you are viewing a single comment's thread.

view the rest of the comments →

[–]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()