简体   繁体   中英

Returning int from a __str__ method in Python

I know, that the purpose of str() method is to return the string representation of an object, so I wanted to test what happens if I force it to make something else.

I've created a class and an object:

class MyClass(object):

    def __str__(self, a=2, b=3):
        return a + b

mc = MyClass()

When I call:

print(str(mc))

The interpreter complains:

TypeError: __str__ returned non-string (type int)

And this is fully understandable because the str() method is trying to return int .

But if I try:

print(mc.__str__())

I get the output: 5.

So why the interpreter allows me to return int when I call __str__ directly, but not when I'm using str(mc) which - as I understand - is also evaluated to mc.__str__() .

str() calls PyObject_Str() . Here is the source code where PyObject_Str() is defined. If you search this document for " __str__ ", you will see where the function calls __str__ and makes sure the return type is actually a string.

The built-in str function (and also repr ) do more than just calling .__str__ (or .__repr__ ) – they also have defaults to cope with objects that don't have a __str__ or __repr__ method, and some cleverness to deal with objects whose string representation is recursive.

You can see the source (in C) for str and repr here and here . As you can see, they enforce the return type of __str__ and __repr__ :

if (!PyUnicode_Check(res)) {
    PyErr_Format(PyExc_TypeError,
                 "__str__ returned non-string (type %.200s)",
                 Py_TYPE(res)->tp_name);
    Py_DECREF(res);
    return NULL;
}

If you just call the __str__ method on an object, Python itself doesn't enforce that any method called __str__ can only return a string – it's the str function that enforces that restriction.

str isn't just

def str(obj):
    return obj.__str__()

I think very few of the standard functions or operators map directly to a magic method like that, although I'm not sure of the exact counts.

str tries __str__ , but it also tries __repr__ if there's no __str__ , and it enforces the str return type. (It also calls the return value's __init__ for technical reasons, which can get weird for str subclasses .) + tries __add__ , but it also tries __radd__ . iter tries __iter__ , but it also tries __getitem__ . The list goes on and on.

__str__ provides a contract: you return a string, and the program won't break when it tries to use a non-string value when the program expects a string. Determining whether __str__ actually obeys that contract is uncomputable in general, so it is up to the programmer to enforce the contract.

As @Juanpa.arrivillaga points out, str is simply stricter about the __str__ method returning what it should be. Your explicit call to __str__ doesn't actually invoke the protocol; it returns an int value, but that value itself has a __str__ method which print calls when it wants a str value.

__str __与Java中的ToString方法类似,您将获得类对象的友好打印。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM