I am trying to understand the __str__
method in Python.
class Test:
def __str__(self):
return 5
t = Test()
print(t.__str__())
In this method it returns an integer value but the print method is able to print it.
But, when I tried print(t)
it threw the error TypeError: __str__ returned non-string (type int)
.
As I understand print(t)
is also calling the __str__(self)
method.
Why didn't print(t.__str__())
want the the string type conversion?
Python __str__() This method returns the string representation of the object. This method is called when print() or str() function is invoked on an object. This method must return the String object.
What is the __repr__ method in Python? In Python, __repr__ is a special method used to represent a class's objects as a string. __repr__ is called by the repr() built-in function. You can define your own string representation of your class objects using the __repr__ method.
The print statement and str() built-in function uses __str__ to display the string representation of the object while the repr() built-in function uses __repr__ to display the object.
Strings are Arrays Like many other popular programming languages, strings in Python are arrays of bytes representing unicode characters. However, Python does not have a character data type, a single character is simply a string with a length of 1.
What you’re doing is equivalent to print(5)
, which works because print
calls __str__
on 5
to get a string. But passing the object, print
calls __str__
on the object and doesn’t get an actual string in response.
It's all about extra checks that python does with some built-in functions.
len() --> __len__() + some checks
str() --> __str__() + some checks
There is a difference between when "you" call a method explicitly or when that method gets called "by Python"! The point is when Python calls your method it will do some checks for you. (That's one of the reasons that we should use those built-in functions instead of calling relevant dunder method.)
We can see that behavior with len()
and __len__()
as well:
class Test:
def __len__(self):
return 'foo'
t = Test()
print(t.__len__()) # fine
print(len(t)) # TypeError: 'str' object cannot be interpreted as an integer
So python checked for returning integer in second print statement! that's what expected from __len__()
.
Same thing happens here. When you call print(t)
Python itself calls __str__()
method, so it does check to see if __str__()
returns a string that is expected or not. (same thing happens with str(t)
)
But, when you say print(t.__str__())
, first, you're calling it's __str__()
method on the instance explicitly by yourself, there is no checking here... what does get back ? number 5
, and then python will run print(5)
.
When you call t.__str__()
directly it is just like any other method. The method __str__
method was overwritten, so there is nothing special about it when calling it directly.
When doing print(t)
invocation happens internally, where some typechecking takes place
if (!PyUnicode_Check(res)) {
_PyErr_Format(tstate, PyExc_TypeError,
"__str__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
The manual states:
The return value must be a string object.
so you should do something like
def __str__(self):
return str(5)
or better, something more meaningful like
def __str__(self) -> str:
return "TestObject with id: {}".format(self.id)
(The return type can be added to the function decalaration so your editor will let you know if it doesn't have the right type.)
When you call print(t)
, print function tries to get the str(t)
value which returns integer. The value has to be str, so it raises an exception. But when you call print(t.__str__())
, it doesn't raise an exception because the method acts like an ordinary method and the return value type doesn't have to be str.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With