- Published on
Truediv
I’m a big fan of the way the /
operator can be used to ‘build’ Path
objects. For example, Path("foo") / "bar"
becomes
foo/bar
. So what makes this possible?
Turns out it’s the __truediv__
method. This method allows you to modify the behaviour of a class when
the /
operator is used. This opens up all sorts of cool things, for example building an url using the builtin urljoin
function.
In the following example I use Pydantic’s RootModel to create a FancyUrl
model that calls the urljoin
function inside
the __truediv__
method and returns the output. I then use this in a ‘Settings’ object to demonstrate a use-case.
from urllib.parse import urljoin
from pydantic import RootModel
from pydantic_settings import BaseSettings
class FancyUrl(RootModel):
root: str
def __truediv__(self, other: str) -> str:
return urljoin(self.root, other)
def __str__(self) -> str:
return self.root
class Settings(BaseSettings):
blog: FancyUrl
settings = Settings(blog="https://marcelblijleven.com")
# This prints https://marcelblijleven.com
print(settings.blog)
# This prints https://marcelblijleven.com/blog/truediv
print(settings.blog / "blog/truediv")
This is already quite nice, but what if you want to add more segments? If you run settings.blog / "blog" / "foo"
you’ll be
presented with an error:
TypeError: unsupported operand type(s) for /: 'str' and 'str'
This is because we return a str
and not a FancyUrl
. So let’s improve the __truediv__
method a bit.
...
from typing import Self # This import is added
...
class FancyUrl(RootModel):
root: str
def __truediv__(self, other: str) -> Self:
# We now set self.root here
self.root = urljoin(self.root, other)
# And return self
return self
def __str__(self) -> str:
return self.root
...
This solves the issue and lets you chain the /
operator on your new FancyUrl!