In Python it is very common to see code that uses method chaining, the main difference with code elsewhere is that this is also combined with returning an object of the same type but modified. This approach usually assumes that objects are inmmutable and only new instances are returned.
The question is whether that violates Law of Demeter.
Some example code from the popular framework called PySpark (from the Java framework Spark):
from pyspark.sql import functions as F
dataframe = (
spark.createDataFrame([], StructType([]))
.withColumn("a", F.rand())
.withColumn("b", F.rand())
.withColumn("c", F.col("a") + F.col("b"))
)
Another way to write this would be:
from pyspark.sql import functions as F
dataframe = spark.createDataFrame([], StructType([]))
dataframe = dataframe.withColumn("a", F.rand())
dataframe = dataframe.withColumn("b", F.rand())
dataframe = dataframe.withColumn("c", F.col("a") + F.col("b"))
This other approach is hard to follow as the same variable is overwritten over and over and keeping track of the value might get too confusing. However, creating new variables for each step polutes the namespace with many variables that will only be used once, hence the method chaining approach that is ubiquitous to the Spark framework.
Equivalent code without any framework would be like:
from dataclasses import dataclass
@dataclass
class Transformer:
data: list[int]
def transform(self, function: Callable[[list[int]], list[int]]):
return Transformer(data=function(self.data))
transformer = (
Transformer([1, 4, 3])
.transform(sorted)
.transform(lambda x: x**2)
)
# or equivanlently
transformer = Transformer([1, 4, 3])
transformer = transformer.transform(sorted)
transformer = transformer.transform(lambda x: x**2)