Most language are aware of the 'return self' idiom, and ignore it if it is
not used in a line. However it is notable that in Python, functions
return None by default.

When I was in CS school my instructor made a huge deal about
the difference between functions, procedures, routines, and methods; many hand-cramping essay questions were ground out with mechanical pencils getting hot in my hands about all that.

Suffice it to say, returning self is the definitive OO way to craft
class methods, but Python allows for multiple return values, tuples, lists, objects, primitives, or None.

Chaining, as they put it, is merely putting the answer to the last operation into the next, and the runtime of Python can optimize that kind of thing. List comprehensions are a built-in form of this. (Very powerful!)

So in Python it is not so important that every method or function return things,
which is why the default is None.

There is a school of thought that every action in a program should report its success, failure, or result back to its invoking context or object, but then
were not talking DOD ADA Requirements here. If you need to get feedback from
a method, go ahead, or not, but try to be consistent about it.

If a method can fail, it should return success or failure or raise an exception to be handled.

One caveat is that if you use the return self idiom, Python will allow you to assign all your methods to variables and you might think you are getting a data result or a list when you are actually getting the object.

Type-restrictive languages scream and yell and break when you try to do this, but interpreted ones (Python, Lua, Lisp) are much more dynamic.

As @Lie Ryan and @Frank Shearar mention, that's called a "fluent interface" but that pattern has been around for a really long time.

The controversial part of that pattern is that in OO, you have mutable state, so a void method has a kind of implied return value of this -- that is, the object with updated state is kind of the return value.

So in an OO language with mutable state, these two are more or less equivalent:

a.doA()
a.doB()
a.doC()

...as opposed to

a.doA().doB().doC()

So I've heard people in the past resist fluent interfaces because they like the first form. Another name I've heard for "fluent interface" is "train wreck" ;)

I say "more or less equivalent", though, because fluent interfaces add a wrinkle. They don't have to "return this". They can "return new". That's a way of attaining immutable objects in OO.