Repository: narwhals-dev/narwhals
Pull request #2117 (2025-02-28 17:11:34)

docs: more concise docstrings(#2068)
  * expr_dt
  * expr_cat
  * dataframe
  * dtypes
  * exp_str - fix slice-
  * expr_list
  * expr_name


<!--
# Thanks for contributing a pull request! 
## Please make sure you see our contribution guidelines: https://github.com/narwhals-dev/narwhals/blob/main/CONTRIBUTING.md
-->

## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [ ] ✨ Feature
- [ ] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [x] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other


Patch:
diff --git a/docs/api-reference/narwhals.md b/docs/api-reference/narwhals.md
index f828a33d..fced41ef 100644
--- a/docs/api-reference/narwhals.md
+++ b/docs/api-reference/narwhals.md
@@ -12,6 +12,7 @@ Here are the top-level functions available in Narwhals.
         - col
         - concat
         - concat_str
+        - exclude
         - from_arrow
         - from_dict
         - from_native
diff --git a/narwhals/__init__.py b/narwhals/__init__.py
index c90179b9..eea037a6 100644
--- a/narwhals/__init__.py
+++ b/narwhals/__init__.py
@@ -40,6 +40,7 @@ from narwhals.functions import any_horizontal
 from narwhals.functions import col
 from narwhals.functions import concat
 from narwhals.functions import concat_str
+from narwhals.functions import exclude
 from narwhals.functions import from_arrow
 from narwhals.functions import from_dict
 from narwhals.functions import from_numpy
@@ -123,6 +124,7 @@ __all__ = [
     "dependencies",
     "dtypes",
     "exceptions",
+    "exclude",
     "from_arrow",
     "from_dict",
     "from_native",
diff --git a/narwhals/_arrow/namespace.py b/narwhals/_arrow/namespace.py
index a58c595a..e740b859 100644
--- a/narwhals/_arrow/namespace.py
+++ b/narwhals/_arrow/namespace.py
@@ -5,6 +5,7 @@ from functools import reduce
 from typing import TYPE_CHECKING
 from typing import Any
 from typing import Callable
+from typing import Container
 from typing import Iterable
 from typing import Literal
 from typing import Sequence
@@ -120,6 +121,35 @@ class ArrowNamespace(CompliantNamespace[ArrowDataFrame, ArrowSeries]):
             *column_names, backend_version=self._backend_version, version=self._version
         )
 
+    def exclude(self: Self, excluded_names: Container[str]) -> ArrowExpr:
+        from narwhals._arrow.series import ArrowSeries
+
+        def evaluate_output_names(df: ArrowDataFrame) -> Sequence[str]:
+            return [
+                column_name
+                for column_name in df.columns
+                if column_name not in excluded_names
+            ]
+
+        def func(df: ArrowDataFrame) -> list[ArrowSeries]:
+            return [
+                ArrowSeries(
+                    df._native_frame[column_name],
+                    name=column_name,
+                    backend_version=df._backend_version,
+                    version=df._version,
+                )
+                for column_name in evaluate_output_names(df)
+            ]
+
+        return self._create_expr_from_callable(
+            func,
+            depth=0,
+            function_name="exclude",
+            evaluate_output_names=evaluate_output_names,
+            alias_output_names=None,
+        )
+
     def nth(self: Self, *column_indices: int) -> ArrowExpr:
         from narwhals._arrow.expr import ArrowExpr
 
diff --git a/narwhals/_dask/namespace.py b/narwhals/_dask/namespace.py
index 5f9fa982..828ad2af 100644
--- a/narwhals/_dask/namespace.py
+++ b/narwhals/_dask/namespace.py
@@ -5,6 +5,7 @@ from functools import reduce
 from typing import TYPE_CHECKING
 from typing import Any
 from typing import Callable
+from typing import Container
 from typing import Iterable
 from typing import Literal
 from typing import Sequence
@@ -67,6 +68,29 @@ class DaskNamespace(CompliantNamespace[DaskLazyFrame, "dx.Series"]):  # pyright:
             *column_names, backend_version=self._backend_version, version=self._version
         )
 
+    def exclude(self: Self, excluded_names: Container[str]) -> DaskExpr:
+        def evaluate_output_names(df: DaskLazyFrame) -> Sequence[str]:
+            return [
+                column_name
+                for column_name in df.columns
+                if column_name not in excluded_names
+            ]
+
+        def func(df: DaskLazyFrame) -> list[dx.Series]:
+            return [
+                df._native_frame[column_name] for column_name in evaluate_output_names(df)
+            ]
+
+        return DaskExpr(
+            func,
+            depth=0,
+            function_name="exclude",
+            evaluate_output_names=evaluate_output_names,
+            alias_output_names=None,
+            backend_version=self._backend_version,
+            version=self._version,
+        )
+
     def nth(self: Self, *column_indices: int) -> DaskExpr:
         return DaskExpr.from_column_indices(
             *column_indices, backend_version=self._backend_version, version=self._version
diff --git a/narwhals/_duckdb/namespace.py b/narwhals/_duckdb/namespace.py
index 4ea72fae..047355e9 100644
--- a/narwhals/_duckdb/namespace.py
+++ b/narwhals/_duckdb/namespace.py
@@ -6,6 +6,7 @@ from functools import reduce
 from typing import TYPE_CHECKING
 from typing import Any
 from typing import Callable
+from typing import Container
 from typing import Literal
 from typing import Sequence
 
@@ -237,6 +238,28 @@ class DuckDBNamespace(CompliantNamespace["DuckDBLazyFrame", "duckdb.Expression"]
             *column_names, backend_version=self._backend_version, version=self._version
         )
 
+    def exclude(self: Self, excluded_names: Container[str]) -> DuckDBExpr:
+        def evaluate_output_names(df: DuckDBLazyFrame) -> Sequence[str]:
+            return [
+                column_name
+                for column_name in df.columns
+                if column_name not in excluded_names
+            ]
+
+        def func(df: DuckDBLazyFrame) -> list[duckdb.Expression]:
+            return [
+                ColumnExpression(column_name) for column_name in evaluate_output_names(df)
+            ]
+
+        return DuckDBExpr(
+            func,
+            function_name="exclude",
+            evaluate_output_names=evaluate_output_names,
+            alias_output_names=None,
+            backend_version=self._backend_version,
+            version=self._version,
+        )
+
     def nth(self: Self, *column_indices: int) -> DuckDBExpr:
         return DuckDBExpr.from_column_indices(
             *column_indices, backend_version=self._backend_version, version=self._version
diff --git a/narwhals/_pandas_like/namespace.py b/narwhals/_pandas_like/namespace.py
index 4e1b887f..75b5cec6 100644
--- a/narwhals/_pandas_like/namespace.py
+++ b/narwhals/_pandas_like/namespace.py
@@ -5,6 +5,7 @@ from functools import reduce
 from typing import TYPE_CHECKING
 from typing import Any
 from typing import Callable
+from typing import Container
 from typing import Iterable
 from typing import Literal
 from typing import Sequence
@@ -115,6 +116,33 @@ class PandasLikeNamespace(CompliantNamespace[PandasLikeDataFrame, PandasLikeSeri
             version=self._version,
         )
 
+    def exclude(self: Self, excluded_names: Container[str]) -> PandasLikeExpr:
+        def evaluate_output_names(df: PandasLikeDataFrame) -> Sequence[str]:
+            return [
+                column_name
+                for column_name in df.columns
+                if column_name not in excluded_names
+            ]
+
+        def func(df: PandasLikeDataFrame) -> list[PandasLikeSeries]:
+            return [
+                PandasLikeSeries(
+                    df._native_frame[column_name],
+                    implementation=df._implementation,
+                    backend_version=df._backend_version,
+                    version=df._version,
+                )
+                for column_name in evaluate_output_names(df)
+            ]
+
+        return self._create_expr_from_callable(
+            func,
+            depth=0,
+            evaluate_output_names=evaluate_output_names,
+            function_name="exclude",
+            alias_output_names=None,
+        )
+
     def nth(self: Self, *column_indices: int) -> PandasLikeExpr:
         return PandasLikeExpr.from_column_indices(
             *column_indices,
diff --git a/narwhals/_spark_like/namespace.py b/narwhals/_spark_like/namespace.py
index 07303aee..91cbd4f3 100644
--- a/narwhals/_spark_like/namespace.py
+++ b/narwhals/_spark_like/namespace.py
@@ -5,6 +5,7 @@ from functools import reduce
 from typing import TYPE_CHECKING
 from typing import Any
 from typing import Callable
+from typing import Container
 from typing import Iterable
 from typing import Literal
 from typing import Sequence
@@ -68,6 +69,27 @@ class SparkLikeNamespace(CompliantNamespace["SparkLikeLazyFrame", "Column"]):  #
             implementation=self._implementation,
         )
 
+    def exclude(self: Self, excluded_names: Container[str]) -> SparkLikeExpr:
+        def evaluate_output_names(df: SparkLikeLazyFrame) -> Sequence[str]:
+            return [
+                column_name
+                for column_name in df.columns
+                if column_name not in excluded_names
+            ]
+
+        def func(df: SparkLikeLazyFrame) -> list[Column]:
+            return [df._F.col(column_name) for column_name in evaluate_output_names(df)]
+
+        return SparkLikeExpr(
+            func,
+            function_name="exclude",
+            evaluate_output_names=evaluate_output_names,
+            alias_output_names=None,
+            backend_version=self._backend_version,
+            version=self._version,
+            implementation=self._implementation,
+        )
+
     def nth(self: Self, *column_indices: int) -> SparkLikeExpr:
         return SparkLikeExpr.from_column_indices(
             *column_indices,
diff --git a/narwhals/dataframe.py b/narwhals/dataframe.py
index 32893b9a..d89a9dbe 100644
--- a/narwhals/dataframe.py
+++ b/narwhals/dataframe.py
@@ -615,41 +615,18 @@ class DataFrame(BaseFrame[DataFrameT]):
 
         Examples:
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> data = {"foo": [1, 2, 3], "bar": [6.0, 7.0, 8.0], "ham": ["a", "b", "c"]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
+            >>> df_native = pd.DataFrame(
+            ...     {"foo": [1, 2, 3], "bar": [6.0, 7.0, 8.0], "ham": ["a", "b", "c"]}
+            ... )
 
             Calling `to_native` on a Narwhals DataFrame returns the native object:
 
-            >>> nw.from_native(df_pd).to_native()
+            >>> nw.from_native(df_native).to_native()
                foo  bar ham
             0    1  6.0   a
             1    2  7.0   b
             2    3  8.0   c
-            >>> nw.from_native(df_pl).to_native()
-            shape: (3, 3)
-            ┌─────┬─────┬─────┐
-            │ foo ┆ bar ┆ ham │
-            │ --- ┆ --- ┆ --- │
-            │ i64 ┆ f64 ┆ str │
-            ╞═════╪═════╪═════╡
-            │ 1   ┆ 6.0 ┆ a   │
-            │ 2   ┆ 7.0 ┆ b   │
-            │ 3   ┆ 8.0 ┆ c   │
-            └─────┴─────┴─────┘
-            >>> nw.from_native(df_pa).to_native()
-            pyarrow.Table
-            foo: int64
-            bar: double
-            ham: string
-            ----
-            foo: [[1,2,3]]
-            bar: [[6,7,8]]
-            ham: [["a","b","c"]]
         """
         return self._compliant_frame._native_frame  # type: ignore[no-any-return]
 
@@ -660,38 +637,13 @@ class DataFrame(BaseFrame[DataFrameT]):
             A pandas DataFrame.
 
         Examples:
-            Construct pandas, Polars (eager) and PyArrow DataFrames:
-
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoDataFrame
-            >>> data = {"foo": [1, 2, 3], "bar": [6.0, 7.0, 8.0], "ham": ["a", "b", "c"]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a library agnostic function:
-
-            >>> def agnostic_to_pandas(df_native: IntoDataFrame) -> pd.DataFrame:
-            ...     df = nw.from_native(df_native)
-            ...     return df.to_pandas()
-
-            We can then pass any supported library such as pandas, Polars (eager), or
-            PyArrow to `agnostic_to_pandas`:
-
-            >>> agnostic_to_pandas(df_pd)
-               foo  bar ham
-            0    1  6.0   a
-            1    2  7.0   b
-            2    3  8.0   c
-            >>> agnostic_to_pandas(df_pl)
-               foo  bar ham
-            0    1  6.0   a
-            1    2  7.0   b
-            2    3  8.0   c
-            >>> agnostic_to_pandas(df_pa)
+            >>> df_native = pl.DataFrame(
+            ...     {"foo": [1, 2, 3], "bar": [6.0, 7.0, 8.0], "ham": ["a", "b", "c"]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.to_pandas()
                foo  bar ham
             0    1  6.0   a
             1    2  7.0   b
@@ -740,32 +692,14 @@ class DataFrame(BaseFrame[DataFrameT]):
             String or None.
 
         Examples:
-            Construct pandas, Polars (eager) and PyArrow DataFrames:
-
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoDataFrame
-            >>> data = {"foo": [1, 2, 3], "bar": [6.0, 7.0, 8.0], "ham": ["a", "b", "c"]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a library agnostic function:
-
-            >>> def agnostic_write_csv(df_native: IntoDataFrame) -> str:
-            ...     df = nw.from_native(df_native)
-            ...     return df.write_csv()
-
-            We can pass any supported library such as pandas, Polars or PyArrow to `agnostic_write_csv`:
-
-            >>> agnostic_write_csv(df_pd)
-            'foo,bar,ham\n1,6.0,a\n2,7.0,b\n3,8.0,c\n'
-            >>> agnostic_write_csv(df_pl)
+            >>> df_native = pd.DataFrame(
+            ...     {"foo": [1, 2, 3], "bar": [6.0, 7.0, 8.0], "ham": ["a", "b", "c"]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.write_csv()
             'foo,bar,ham\n1,6.0,a\n2,7.0,b\n3,8.0,c\n'
-            >>> agnostic_write_csv(df_pa)
-            '"foo","bar","ham"\n1,6,"a"\n2,7,"b"\n3,8,"c"\n'
 
             If we had passed a file name to `write_csv`, it would have been
             written to that file.
diff --git a/narwhals/dtypes.py b/narwhals/dtypes.py
index 75678b0b..b4bbb714 100644
--- a/narwhals/dtypes.py
+++ b/narwhals/dtypes.py
@@ -119,20 +119,11 @@ class Int64(SignedIntegerType):
     """64-bit signed integer type.
 
     Examples:
-        >>> import pandas as pd
         >>> import polars as pl
-        >>> import pyarrow as pa
         >>> import narwhals as nw
-        >>> data = [2, 1, 3, 7]
-        >>> ser_pd = pd.Series(data)
-        >>> ser_pl = pl.Series(data)
-        >>> ser_pa = pa.chunked_array([data])
-
-        >>> nw.from_native(ser_pd, series_only=True).dtype
-        Int64
-        >>> nw.from_native(ser_pl, series_only=True).dtype
-        Int64
-        >>> nw.from_native(ser_pa, series_only=True).dtype
+        >>> s_native = pl.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.Int64).dtype
         Int64
     """
 
@@ -141,24 +132,11 @@ class Int32(SignedIntegerType):
     """32-bit signed integer type.
 
     Examples:
-        >>> import pandas as pd
-        >>> import polars as pl
         >>> import pyarrow as pa
         >>> import narwhals as nw
-        >>> data = [2, 1, 3, 7]
-        >>> ser_pd = pd.Series(data)
-        >>> ser_pl = pl.Series(data)
-        >>> ser_pa = pa.chunked_array([data])
-
-        >>> def func(ser):
-        ...     ser_nw = nw.from_native(ser, series_only=True)
-        ...     return ser_nw.cast(nw.Int32).dtype
-
-        >>> func(ser_pd)
-        Int32
-        >>> func(ser_pl)
-        Int32
-        >>> func(ser_pa)
+        >>> s_native = pa.chunked_array([[2, 1, 3, 7]])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.Int32).dtype
         Int32
     """
 
@@ -167,24 +145,11 @@ class Int16(SignedIntegerType):
     """16-bit signed integer type.
 
     Examples:
-        >>> import pandas as pd
         >>> import polars as pl
-        >>> import pyarrow as pa
         >>> import narwhals as nw
-        >>> data = [2, 1, 3, 7]
-        >>> ser_pd = pd.Series(data)
-        >>> ser_pl = pl.Series(data)
-        >>> ser_pa = pa.chunked_array([data])
-
-        >>> def func(ser):
-        ...     ser_nw = nw.from_native(ser, series_only=True)
-        ...     return ser_nw.cast(nw.Int16).dtype
-
-        >>> func(ser_pd)
-        Int16
-        >>> func(ser_pl)
-        Int16
-        >>> func(ser_pa)
+        >>> s_native = pl.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.Int16).dtype
         Int16
     """
 
@@ -193,25 +158,12 @@ class Int8(SignedIntegerType):
     """8-bit signed integer type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [2, 1, 3, 7]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> def func(ser):
-       ...     ser_nw = nw.from_native(ser, series_only=True)
-       ...     return ser_nw.cast(nw.Int8).dtype
-
-       >>> func(ser_pd)
-       Int8
-       >>> func(ser_pl)
-       Int8
-       >>> func(ser_pa)
-       Int8
+        >>> import pandas as pd
+        >>> import narwhals as nw
+        >>> s_native = pd.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.Int8).dtype
+        Int8
     """
 
 
@@ -223,25 +175,12 @@ class UInt64(UnsignedIntegerType):
     """64-bit unsigned integer type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [2, 1, 3, 7]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> def func(ser):
-       ...     ser_nw = nw.from_native(ser, series_only=True)
-       ...     return ser_nw.cast(nw.UInt64).dtype
-
-       >>> func(ser_pd)
-       UInt64
-       >>> func(ser_pl)
-       UInt64
-       >>> func(ser_pa)
-       UInt64
+        >>> import pandas as pd
+        >>> import narwhals as nw
+        >>> s_native = pd.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.UInt64).dtype
+        UInt64
     """
 
 
@@ -249,25 +188,12 @@ class UInt32(UnsignedIntegerType):
     """32-bit unsigned integer type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [2, 1, 3, 7]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> def func(ser):
-       ...     ser_nw = nw.from_native(ser, series_only=True)
-       ...     return ser_nw.cast(nw.UInt32).dtype
-
-       >>> func(ser_pd)
-       UInt32
-       >>> func(ser_pl)
-       UInt32
-       >>> func(ser_pa)
-       UInt32
+        >>> import polars as pl
+        >>> import narwhals as nw
+        >>> s_native = pl.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.UInt32).dtype
+        UInt32
     """
 
 
@@ -275,25 +201,12 @@ class UInt16(UnsignedIntegerType):
     """16-bit unsigned integer type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [2, 1, 3, 7]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> def func(ser):
-       ...     ser_nw = nw.from_native(ser, series_only=True)
-       ...     return ser_nw.cast(nw.UInt16).dtype
-
-       >>> func(ser_pd)
-       UInt16
-       >>> func(ser_pl)
-       UInt16
-       >>> func(ser_pa)
-       UInt16
+        >>> import polars as pl
+        >>> import narwhals as nw
+        >>> s_native = pl.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.UInt16).dtype
+        UInt16
     """
 
 
@@ -301,25 +214,12 @@ class UInt8(UnsignedIntegerType):
     """8-bit unsigned integer type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [2, 1, 3, 7]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> def func(ser):
-       ...     ser_nw = nw.from_native(ser, series_only=True)
-       ...     return ser_nw.cast(nw.UInt8).dtype
-
-       >>> func(ser_pd)
-       UInt8
-       >>> func(ser_pl)
-       UInt8
-       >>> func(ser_pa)
-       UInt8
+        >>> import polars as pl
+        >>> import narwhals as nw
+        >>> s_native = pl.Series([2, 1, 3, 7])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.UInt8).dtype
+        UInt8
     """
 
 
@@ -327,20 +227,11 @@ class Float64(FloatType):
     """64-bit floating point type.
 
     Examples:
-        >>> import pandas as pd
-        >>> import polars as pl
         >>> import pyarrow as pa
         >>> import narwhals as nw
-        >>> data = [0.001, 0.1, 0.01, 0.1]
-        >>> ser_pd = pd.Series(data)
-        >>> ser_pl = pl.Series(data)
-        >>> ser_pa = pa.chunked_array([data])
-
-        >>> nw.from_native(ser_pd, series_only=True).dtype
-        Float64
-        >>> nw.from_native(ser_pl, series_only=True).dtype
-        Float64
-        >>> nw.from_native(ser_pa, series_only=True).dtype
+        >>> s_native = pa.chunked_array([[0.001, 0.1, 0.01, 0.1]])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.Float64).dtype
         Float64
     """
 
@@ -349,25 +240,12 @@ class Float32(FloatType):
     """32-bit floating point type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [0.001, 0.1, 0.01, 0.1]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> def func(ser):
-       ...     ser_nw = nw.from_native(ser, series_only=True)
-       ...     return ser_nw.cast(nw.Float32).dtype
-
-       >>> func(ser_pd)
-       Float32
-       >>> func(ser_pl)
-       Float32
-       >>> func(ser_pa)
-       Float32
+        >>> import polars as pl
+        >>> import narwhals as nw
+        >>> s_native = pl.Series([0.001, 0.1, 0.01, 0.1])
+        >>> s = nw.from_native(s_native, series_only=True)
+        >>> s.cast(nw.Float32).dtype
+        Float32
     """
 
 
@@ -375,21 +253,11 @@ class String(DType):
     """UTF-8 encoded string type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = ["beluga", "narwhal", "orca", "vaquita"]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> nw.from_native(ser_pd, series_only=True).dtype
-       String
-       >>> nw.from_native(ser_pl, series_only=True).dtype
-       String
-       >>> nw.from_native(ser_pa, series_only=True).dtype
-       String
+        >>> import pandas as pd
+        >>> import narwhals as nw
+        >>> s_native = pd.Series(["beluga", "narwhal", "orca", "vaquita"])
+        >>> nw.from_native(s_native, series_only=True).dtype
+        String
     """
 
 
@@ -397,21 +265,11 @@ class Boolean(DType):
     """Boolean type.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = [True, False, False, True]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> nw.from_native(ser_pd, series_only=True).dtype
-       Boolean
-       >>> nw.from_native(ser_pl, series_only=True).dtype
-       Boolean
-       >>> nw.from_native(ser_pa, series_only=True).dtype
-       Boolean
+        >>> import pyarrow as pa
+        >>> import narwhals as nw
+        >>> s_native = pa.chunked_array([[True, False, False, True]])
+        >>> nw.from_native(s_native, series_only=True).dtype
+        Boolean
     """
 
 
@@ -419,18 +277,12 @@ class Object(DType):
     """Data type for wrapping arbitrary Python objects.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> class Foo: ...
-       >>> ser_pd = pd.Series([Foo(), Foo()])
-       >>> ser_pl = pl.Series([Foo(), Foo()])
-
-       >>> nw.from_native(ser_pd, series_only=True).dtype
-       Object
-       >>> nw.from_native(ser_pl, series_only=True).dtype
-       Object
+        >>> import pandas as pd
+        >>> import narwhals as nw
+        >>> class Foo: ...
+        >>> s_native = pd.Series([Foo(), Foo()])
+        >>> nw.from_native(s_native, series_only=True).dtype
+        Object
     """
 
 
@@ -438,13 +290,11 @@ class Unknown(DType):
     """Type representing DataType values that could not be determined statically.
 
     Examples:
-       >>> import pandas as pd
-       >>> import narwhals as nw
-       >>> data = pd.period_range("2000-01", periods=4, freq="M")
-       >>> ser_pd = pd.Series(data)
-
-       >>> nw.from_native(ser_pd, series_only=True).dtype
-       Unknown
+        >>> import pandas as pd
+        >>> import narwhals as nw
+        >>> s_native = pd.Series(pd.period_range("2000-01", periods=4, freq="M"))
+        >>> nw.from_native(s_native, series_only=True).dtype
+        Unknown
     """
 
 
@@ -470,32 +320,15 @@ class Datetime(TemporalType, metaclass=_DatetimeMeta):
         Adapted from [Polars implementation](https://github.com/pola-rs/polars/blob/py-1.7.1/py-polars/polars/datatypes/classes.py#L398-L457)
 
     Examples:
-        >>> import pandas as pd
+        >>> from datetime import datetime, timedelta
         >>> import polars as pl
-        >>> import pyarrow as pa
-        >>> import pyarrow.compute as pc
         >>> import narwhals as nw
-        >>> from datetime import datetime, timedelta
-        >>> data = [datetime(2024, 12, 9) + timedelta(days=n) for n in range(5)]
-        >>> ser_pd = (
-        ...     pd.Series(data)
-        ...     .dt.tz_localize("Africa/Accra")
-        ...     .astype("datetime64[ms, Africa/Accra]")
-        ... )
-        >>> ser_pl = (
-        ...     pl.Series(data)
+        >>> s_native = (
+        ...     pl.Series([datetime(2024, 12, 9) + timedelta(days=n) for n in range(5)])
         ...     .cast(pl.Datetime("ms"))
         ...     .dt.replace_time_zone("Africa/Accra")
         ... )
-        >>> ser_pa = pc.assume_timezone(
-        ...     pa.chunked_array([data], type=pa.timestamp("ms")), "Africa/Accra"
-        ... )
-
-        >>> nw.from_native(ser_pd, series_only=True).dtype
-        Datetime(time_unit='ms', time_zone='Africa/Accra')
-        >>> nw.from_native(ser_pl, series_only=True).dtype
-        Datetime(time_unit='ms', time_zone='Africa/Accra')
-        >>> nw.from_native(ser_pa, series_only=True).dtype
+        >>> nw.from_native(s_native, series_only=True).dtype
         Datetime(time_unit='ms', time_zone='Africa/Accra')
     """
 
@@ -550,21 +383,13 @@ class Duration(TemporalType, metaclass=_DurationMeta):
         Adapted from [Polars implementation](https://github.com/pola-rs/polars/blob/py-1.7.1/py-polars/polars/datatypes/classes.py#L460-L502)
 
     Examples:
-        >>> import pandas as pd
-        >>> import polars as pl
+        >>> from datetime import timedelta
         >>> import pyarrow as pa
         >>> import narwhals as nw
-        >>> from datetime import timedelta
-        >>> data = [timedelta(seconds=d) for d in range(1, 4)]
-        >>> ser_pd = pd.Series(data).astype("timedelta64[ms]")
-        >>> ser_pl = pl.Series(data).cast(pl.Duration("ms"))
-        >>> ser_pa = pa.chunked_array([data], type=pa.duration("ms"))
-
-        >>> nw.from_native(ser_pd, series_only=True).dtype
-        Duration(time_unit='ms')
-        >>> nw.from_native(ser_pl, series_only=True).dtype
-        Duration(time_unit='ms')
-        >>> nw.from_native(ser_pa, series_only=True).dtype
+        >>> s_native = pa.chunked_array(
+        ...     [[timedelta(seconds=d) for d in range(1, 4)]], type=pa.duration("ms")
+        ... )
+        >>> nw.from_native(s_native, series_only=True).dtype
         Duration(time_unit='ms')
     """
 
@@ -599,21 +424,11 @@ class Categorical(DType):
     """A categorical encoding of a set of strings.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> data = ["beluga", "narwhal", "orca", "vaquita"]
-       >>> ser_pd = pd.Series(data)
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> nw.from_native(ser_pd, series_only=True).cast(nw.Categorical).dtype
-       Categorical
-       >>> nw.from_native(ser_pl, series_only=True).cast(nw.Categorical).dtype
-       Categorical
-       >>> nw.from_native(ser_pa, series_only=True).cast(nw.Categorical).dtype
-       Categorical
+        >>> import polars as pl
+        >>> import narwhals as nw
+        >>> s_native = pl.Series(["beluga", "narwhal", "orca"])
+        >>> nw.from_native(s_native, series_only=True).cast(nw.Categorical).dtype
+        Categorical
     """
 
 
@@ -625,10 +440,9 @@ class Enum(DType):
     Examples:
        >>> import polars as pl
        >>> import narwhals as nw
-       >>> data = ["beluga", "narwhal", "orca", "vaquita"]
-       >>> ser_pl = pl.Series(data, dtype=pl.Enum(data))
-
-       >>> nw.from_native(ser_pl, series_only=True).dtype
+       >>> data = ["beluga", "narwhal", "orca"]
+       >>> s_native = pl.Series(data, dtype=pl.Enum(data))
+       >>> nw.from_native(s_native, series_only=True).dtype
        Enum
     """
 
@@ -667,16 +481,12 @@ class Struct(NestedType):
             objects or a mapping of column names to data types.
 
     Examples:
-       >>> import polars as pl
        >>> import pyarrow as pa
        >>> import narwhals as nw
-       >>> data = [{"a": 1, "b": ["narwhal", "beluga"]}, {"a": 2, "b": ["orca"]}]
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> nw.from_native(ser_pl, series_only=True).dtype
-       Struct({'a': Int64, 'b': List(String)})
-       >>> nw.from_native(ser_pa, series_only=True).dtype
+       >>> s_native = pa.chunked_array(
+       ...     [[{"a": 1, "b": ["narwhal", "beluga"]}, {"a": 2, "b": ["orca"]}]]
+       ... )
+       >>> nw.from_native(s_native, series_only=True).dtype
        Struct({'a': Int64, 'b': List(String)})
     """
 
@@ -731,19 +541,13 @@ class List(NestedType):
 
     Examples:
        >>> import pandas as pd
-       >>> import polars as pl
        >>> import pyarrow as pa
        >>> import narwhals as nw
-       >>> data = [["narwhal", "orca"], ["beluga", "vaquita"]]
-       >>> ser_pd = pd.Series(data, dtype=pd.ArrowDtype(pa.large_list(pa.large_string())))
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> nw.from_native(ser_pd, series_only=True).dtype
-       List(String)
-       >>> nw.from_native(ser_pl, series_only=True).dtype
-       List(String)
-       >>> nw.from_native(ser_pa, series_only=True).dtype
+       >>> s_native = pd.Series(
+       ...     [["narwhal", "orca"], ["beluga", "vaquita"]],
+       ...     dtype=pd.ArrowDtype(pa.large_list(pa.large_string())),
+       ... )
+       >>> nw.from_native(s_native, series_only=True).dtype
        List(String)
     """
 
@@ -783,20 +587,10 @@ class Array(NestedType):
         shape: The shape of the arrays.
 
     Examples:
-        >>> import pandas as pd
         >>> import polars as pl
-        >>> import pyarrow as pa
         >>> import narwhals as nw
-        >>> data = [[1, 2], [3, 4], [5, 6]]
-        >>> ser_pd = pd.Series(data, dtype=pd.ArrowDtype(pa.list_(pa.int32(), 2)))
-        >>> ser_pl = pl.Series(data, dtype=pl.Array(pl.Int32, 2))
-        >>> ser_pa = pa.chunked_array([data], type=pa.list_(pa.int32(), 2))
-
-        >>> nw.from_native(ser_pd, series_only=True).dtype
-        Array(Int32, shape=(2,))
-        >>> nw.from_native(ser_pl, series_only=True).dtype
-        Array(Int32, shape=(2,))
-        >>> nw.from_native(ser_pa, series_only=True).dtype
+        >>> s_native = pl.Series([[1, 2], [3, 4], [5, 6]], dtype=pl.Array(pl.Int32, 2))
+        >>> nw.from_native(s_native, series_only=True).dtype
         Array(Int32, shape=(2,))
     """
 
@@ -860,20 +654,12 @@ class Date(TemporalType):
     """Data type representing a calendar date.
 
     Examples:
-       >>> import pandas as pd
-       >>> import polars as pl
-       >>> import pyarrow as pa
-       >>> import narwhals as nw
-       >>> from datetime import date, timedelta
-       >>> data = [date(2024, 12, 1) + timedelta(days=d) for d in range(4)]
-       >>> ser_pd = pd.Series(data, dtype="date32[pyarrow]")
-       >>> ser_pl = pl.Series(data)
-       >>> ser_pa = pa.chunked_array([data])
-
-       >>> nw.from_native(ser_pd, series_only=True).dtype
-       Date
-       >>> nw.from_native(ser_pl, series_only=True).dtype
-       Date
-       >>> nw.from_native(ser_pa, series_only=True).dtype
-       Date
+        >>> from datetime import date, timedelta
+        >>> import pyarrow as pa
+        >>> import narwhals as nw
+        >>> s_native = pa.chunked_array(
+        ...     [[date(2024, 12, 1) + timedelta(days=d) for d in range(4)]]
+        ... )
+        >>> nw.from_native(s_native, series_only=True).dtype
+        Date
     """
diff --git a/narwhals/expr_cat.py b/narwhals/expr_cat.py
index 4b08d656..14185933 100644
--- a/narwhals/expr_cat.py
+++ b/narwhals/expr_cat.py
@@ -25,34 +25,14 @@ class ExprCatNamespace(Generic[ExprT]):
             A new expression.
 
         Examples:
-            Let's create some dataframes:
-
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"fruits": ["apple", "mango", "mango"]}
-            >>> df_pd = pd.DataFrame(data, dtype="category")
-            >>> df_pl = pl.DataFrame(data, schema={"fruits": pl.Categorical})
-
-            We define a dataframe-agnostic function to get unique categories
-            from column 'fruits':
-
-            >>> def agnostic_cat_get_categories(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("fruits").cat.get_categories()).to_native()
-
-           We can then pass any supported library such as pandas or Polars to
-           `agnostic_cat_get_categories`:
-
-            >>> agnostic_cat_get_categories(df_pd)
-              fruits
-            0  apple
-            1  mango
-
-            >>> agnostic_cat_get_categories(df_pl)
+            >>> df_native = pl.DataFrame(
+            ...     {"fruits": ["apple", "mango", "mango"]},
+            ...     schema={"fruits": pl.Categorical},
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("fruits").cat.get_categories()).to_native()
             shape: (2, 1)
             ┌────────┐
             │ fruits │
diff --git a/narwhals/expr_dt.py b/narwhals/expr_dt.py
index 178009f6..b65406f1 100644
--- a/narwhals/expr_dt.py
+++ b/narwhals/expr_dt.py
@@ -28,34 +28,13 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [datetime(2012, 1, 7, 10, 20), datetime(2023, 3, 10, 11, 32)]
-            ... }
-            >>> df_pd = pd.DataFrame(data).convert_dtypes(dtype_backend="pyarrow")
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a library agnostic function:
-
-            >>> def agnostic_dt_date(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("a").dt.date()).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_date`:
-
-            >>> agnostic_dt_date(df_pd)
-                        a
-            0  2012-01-07
-            1  2023-03-10
-
-            >>> agnostic_dt_date(df_pl)
+            >>> df_native = pl.DataFrame(
+            ...     {"a": [datetime(2012, 1, 7, 10), datetime(2027, 12, 13)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("a").dt.date()).to_native()
             shape: (2, 1)
             ┌────────────┐
             │ a          │
@@ -63,14 +42,8 @@ class ExprDateTimeNamespace(Generic[ExprT]):
             │ date       │
             ╞════════════╡
             │ 2012-01-07 │
-            │ 2023-03-10 │
+            │ 2027-12-13 │
             └────────────┘
-
-            >>> agnostic_dt_date(df_pa)
-            pyarrow.Table
-            a: date32[day]
-            ----
-            a: [[2012-01-07,2023-03-10]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.date(), self._expr._metadata
@@ -87,58 +60,19 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import datetime
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 6, 1),
-            ...         datetime(2024, 12, 13),
-            ...         datetime(2065, 1, 1),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_year(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.year().alias("year")
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_year`:
-
-            >>> agnostic_dt_year(df_pd)
-                datetime  year
-            0 1978-06-01  1978
-            1 2024-12-13  2024
-            2 2065-01-01  2065
-
-            >>> agnostic_dt_year(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────┬──────┐
-            │ datetime            ┆ year │
-            │ ---                 ┆ ---  │
-            │ datetime[μs]        ┆ i32  │
-            ╞═════════════════════╪══════╡
-            │ 1978-06-01 00:00:00 ┆ 1978 │
-            │ 2024-12-13 00:00:00 ┆ 2024 │
-            │ 2065-01-01 00:00:00 ┆ 2065 │
-            └─────────────────────┴──────┘
-
-            >>> agnostic_dt_year(df_pa)
-            pyarrow.Table
-            datetime: timestamp[us]
-            year: int64
-            ----
-            datetime: [[1978-06-01 00:00:00.000000,2024-12-13 00:00:00.000000,2065-01-01 00:00:00.000000]]
-            year: [[1978,2024,2065]]
+            >>> df_native = pd.DataFrame(
+            ...     {"a": [datetime(1978, 6, 1), datetime(2065, 1, 1)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("a").dt.year().alias("year"))
+            ┌──────────────────┐
+            |Narwhals DataFrame|
+            |------------------|
+            |           a  year|
+            |0 1978-06-01  1978|
+            |1 2065-01-01  2065|
+            └──────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.year(), self._expr._metadata
@@ -154,59 +88,17 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 6, 1),
-            ...         datetime(2024, 12, 13),
-            ...         datetime(2065, 1, 1),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_month(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.month().alias("month"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_month`:
-
-            >>> agnostic_dt_month(df_pd)
-                datetime  month
-            0 1978-06-01      6
-            1 2024-12-13     12
-            2 2065-01-01      1
-
-            >>> agnostic_dt_month(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────┬───────┐
-            │ datetime            ┆ month │
-            │ ---                 ┆ ---   │
-            │ datetime[μs]        ┆ i8    │
-            ╞═════════════════════╪═══════╡
-            │ 1978-06-01 00:00:00 ┆ 6     │
-            │ 2024-12-13 00:00:00 ┆ 12    │
-            │ 2065-01-01 00:00:00 ┆ 1     │
-            └─────────────────────┴───────┘
-
-            >>> agnostic_dt_month(df_pa)
+            >>> df_native = pa.table({"a": [datetime(1978, 6, 1), datetime(2065, 1, 1)]})
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("a").dt.month().alias("month")).to_native()
             pyarrow.Table
-            datetime: timestamp[us]
+            a: timestamp[us]
             month: int64
             ----
-            datetime: [[1978-06-01 00:00:00.000000,2024-12-13 00:00:00.000000,2065-01-01 00:00:00.000000]]
-            month: [[6,12,1]]
+            a: [[1978-06-01 00:00:00.000000,2065-01-01 00:00:00.000000]]
+            month: [[6,1]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.month(),
@@ -223,59 +115,17 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 6, 1),
-            ...         datetime(2024, 12, 13),
-            ...         datetime(2065, 1, 1),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_day(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.day().alias("day"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_day`:
-
-            >>> agnostic_dt_day(df_pd)
-                datetime  day
-            0 1978-06-01    1
-            1 2024-12-13   13
-            2 2065-01-01    1
-
-            >>> agnostic_dt_day(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────┬─────┐
-            │ datetime            ┆ day │
-            │ ---                 ┆ --- │
-            │ datetime[μs]        ┆ i8  │
-            ╞═════════════════════╪═════╡
-            │ 1978-06-01 00:00:00 ┆ 1   │
-            │ 2024-12-13 00:00:00 ┆ 13  │
-            │ 2065-01-01 00:00:00 ┆ 1   │
-            └─────────────────────┴─────┘
-
-            >>> agnostic_dt_day(df_pa)
+            >>> df_native = pa.table({"a": [datetime(1978, 6, 1), datetime(2065, 1, 1)]})
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("a").dt.day().alias("day")).to_native()
             pyarrow.Table
-            datetime: timestamp[us]
+            a: timestamp[us]
             day: int64
             ----
-            datetime: [[1978-06-01 00:00:00.000000,2024-12-13 00:00:00.000000,2065-01-01 00:00:00.000000]]
-            day: [[1,13,1]]
+            a: [[1978-06-01 00:00:00.000000,2065-01-01 00:00:00.000000]]
+            day: [[1,1]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.day(), self._expr._metadata
@@ -291,59 +141,26 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 1, 1, 1),
-            ...         datetime(2024, 10, 13, 5),
-            ...         datetime(2065, 1, 1, 10),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_hour(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.hour().alias("hour")
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_hour`:
-
-            >>> agnostic_dt_hour(df_pd)
-                         datetime  hour
-            0 1978-01-01 01:00:00     1
-            1 2024-10-13 05:00:00     5
-            2 2065-01-01 10:00:00    10
-
-            >>> agnostic_dt_hour(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────┬──────┐
-            │ datetime            ┆ hour │
-            │ ---                 ┆ ---  │
-            │ datetime[μs]        ┆ i8   │
-            ╞═════════════════════╪══════╡
-            │ 1978-01-01 01:00:00 ┆ 1    │
-            │ 2024-10-13 05:00:00 ┆ 5    │
-            │ 2065-01-01 10:00:00 ┆ 10   │
-            └─────────────────────┴──────┘
-
-            >>> agnostic_dt_hour(df_pa)
-            pyarrow.Table
-            datetime: timestamp[us]
-            hour: int64
-            ----
-            datetime: [[1978-01-01 01:00:00.000000,2024-10-13 05:00:00.000000,2065-01-01 10:00:00.000000]]
-            hour: [[1,5,10]]
+            >>> df_native = pl.DataFrame(
+            ...     {"a": [datetime(1978, 1, 1, 1), datetime(2065, 1, 1, 10)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("a").dt.hour().alias("hour"))
+            ┌──────────────────────────────┐
+            |      Narwhals DataFrame      |
+            |------------------------------|
+            |shape: (2, 2)                 |
+            |┌─────────────────────┬──────┐|
+            |│ a                   ┆ hour │|
+            |│ ---                 ┆ ---  │|
+            |│ datetime[μs]        ┆ i8   │|
+            |╞═════════════════════╪══════╡|
+            |│ 1978-01-01 01:00:00 ┆ 1    │|
+            |│ 2065-01-01 10:00:00 ┆ 10   │|
+            |└─────────────────────┴──────┘|
+            └──────────────────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.hour(), self._expr._metadata
@@ -360,58 +177,15 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import datetime
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 1, 1, 1, 1),
-            ...         datetime(2024, 10, 13, 5, 30),
-            ...         datetime(2065, 1, 1, 10, 20),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_minute(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.minute().alias("minute"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_minute`:
-
-            >>> agnostic_dt_minute(df_pd)
-                         datetime  minute
+            >>> df_native = pd.DataFrame(
+            ...     {"a": [datetime(1978, 1, 1, 1, 1), datetime(2065, 1, 1, 10, 20)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("a").dt.minute().alias("minute")).to_native()
+                                a  minute
             0 1978-01-01 01:01:00       1
-            1 2024-10-13 05:30:00      30
-            2 2065-01-01 10:20:00      20
-
-            >>> agnostic_dt_minute(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────┬────────┐
-            │ datetime            ┆ minute │
-            │ ---                 ┆ ---    │
-            │ datetime[μs]        ┆ i8     │
-            ╞═════════════════════╪════════╡
-            │ 1978-01-01 01:01:00 ┆ 1      │
-            │ 2024-10-13 05:30:00 ┆ 30     │
-            │ 2065-01-01 10:20:00 ┆ 20     │
-            └─────────────────────┴────────┘
-
-            >>> agnostic_dt_minute(df_pa)
-            pyarrow.Table
-            datetime: timestamp[us]
-            minute: int64
-            ----
-            datetime: [[1978-01-01 01:01:00.000000,2024-10-13 05:30:00.000000,2065-01-01 10:20:00.000000]]
-            minute: [[1,30,20]]
+            1 2065-01-01 10:20:00      20
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.minute(),
@@ -426,59 +200,24 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 1, 1, 1, 1, 1),
-            ...         datetime(2024, 10, 13, 5, 30, 14),
-            ...         datetime(2065, 1, 1, 10, 20, 30),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_second(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.second().alias("second"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_second`:
-
-            >>> agnostic_dt_second(df_pd)
-                         datetime  second
-            0 1978-01-01 01:01:01       1
-            1 2024-10-13 05:30:14      14
-            2 2065-01-01 10:20:30      30
-
-            >>> agnostic_dt_second(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────┬────────┐
-            │ datetime            ┆ second │
-            │ ---                 ┆ ---    │
-            │ datetime[μs]        ┆ i8     │
-            ╞═════════════════════╪════════╡
-            │ 1978-01-01 01:01:01 ┆ 1      │
-            │ 2024-10-13 05:30:14 ┆ 14     │
-            │ 2065-01-01 10:20:30 ┆ 30     │
-            └─────────────────────┴────────┘
-
-            >>> agnostic_dt_second(df_pa)
+            >>> df_native = pa.table(
+            ...     {
+            ...         "a": [
+            ...             datetime(1978, 1, 1, 1, 1, 1),
+            ...             datetime(2065, 1, 1, 10, 20, 30),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("a").dt.second().alias("second")).to_native()
             pyarrow.Table
-            datetime: timestamp[us]
+            a: timestamp[us]
             second: int64
             ----
-            datetime: [[1978-01-01 01:01:01.000000,2024-10-13 05:30:14.000000,2065-01-01 10:20:30.000000]]
-            second: [[1,14,30]]
+            a: [[1978-01-01 01:01:01.000000,2065-01-01 10:20:30.000000]]
+            second: [[1,30]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.second(),
@@ -493,59 +232,26 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 1, 1, 1, 1, 1, 0),
-            ...         datetime(2024, 10, 13, 5, 30, 14, 505000),
-            ...         datetime(2065, 1, 1, 10, 20, 30, 67000),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_millisecond(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.millisecond().alias("millisecond"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_millisecond`:
-
-            >>> agnostic_dt_millisecond(df_pd)
-                             datetime  millisecond
-            0 1978-01-01 01:01:01.000            0
-            1 2024-10-13 05:30:14.505          505
-            2 2065-01-01 10:20:30.067           67
-
-            >>> agnostic_dt_millisecond(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────────┬─────────────┐
-            │ datetime                ┆ millisecond │
-            │ ---                     ┆ ---         │
-            │ datetime[μs]            ┆ i32         │
-            ╞═════════════════════════╪═════════════╡
-            │ 1978-01-01 01:01:01     ┆ 0           │
-            │ 2024-10-13 05:30:14.505 ┆ 505         │
-            │ 2065-01-01 10:20:30.067 ┆ 67          │
-            └─────────────────────────┴─────────────┘
-
-            >>> agnostic_dt_millisecond(df_pa)
+            >>> df_native = pa.table(
+            ...     {
+            ...         "a": [
+            ...             datetime(1978, 1, 1, 1, 1, 1, 0),
+            ...             datetime(2065, 1, 1, 10, 20, 30, 67000),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     nw.col("a").dt.millisecond().alias("millisecond")
+            ... ).to_native()
             pyarrow.Table
-            datetime: timestamp[us]
+            a: timestamp[us]
             millisecond: int64
             ----
-            datetime: [[1978-01-01 01:01:01.000000,2024-10-13 05:30:14.505000,2065-01-01 10:20:30.067000]]
-            millisecond: [[0,505,67]]
+            a: [[1978-01-01 01:01:01.000000,2065-01-01 10:20:30.067000]]
+            millisecond: [[0,67]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.millisecond(),
@@ -560,59 +266,26 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 1, 1, 1, 1, 1, 0),
-            ...         datetime(2024, 10, 13, 5, 30, 14, 505000),
-            ...         datetime(2065, 1, 1, 10, 20, 30, 67000),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_microsecond(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.microsecond().alias("microsecond"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_microsecond`:
-
-            >>> agnostic_dt_microsecond(df_pd)
-                             datetime  microsecond
-            0 1978-01-01 01:01:01.000            0
-            1 2024-10-13 05:30:14.505       505000
-            2 2065-01-01 10:20:30.067        67000
-
-            >>> agnostic_dt_microsecond(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────────┬─────────────┐
-            │ datetime                ┆ microsecond │
-            │ ---                     ┆ ---         │
-            │ datetime[μs]            ┆ i32         │
-            ╞═════════════════════════╪═════════════╡
-            │ 1978-01-01 01:01:01     ┆ 0           │
-            │ 2024-10-13 05:30:14.505 ┆ 505000      │
-            │ 2065-01-01 10:20:30.067 ┆ 67000       │
-            └─────────────────────────┴─────────────┘
-
-            >>> agnostic_dt_microsecond(df_pa)
+            >>> df_native = pa.table(
+            ...     {
+            ...         "a": [
+            ...             datetime(1978, 1, 1, 1, 1, 1, 0),
+            ...             datetime(2065, 1, 1, 10, 20, 30, 67000),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     nw.col("a").dt.microsecond().alias("microsecond")
+            ... ).to_native()
             pyarrow.Table
-            datetime: timestamp[us]
+            a: timestamp[us]
             microsecond: int64
             ----
-            datetime: [[1978-01-01 01:01:01.000000,2024-10-13 05:30:14.505000,2065-01-01 10:20:30.067000]]
-            microsecond: [[0,505000,67000]]
+            a: [[1978-01-01 01:01:01.000000,2065-01-01 10:20:30.067000]]
+            microsecond: [[0,67000]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.microsecond(),
@@ -627,59 +300,26 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "datetime": [
-            ...         datetime(1978, 1, 1, 1, 1, 1, 0),
-            ...         datetime(2024, 10, 13, 5, 30, 14, 500000),
-            ...         datetime(2065, 1, 1, 10, 20, 30, 60000),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_nanosecond(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("datetime").dt.nanosecond().alias("nanosecond"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_nanosecond`:
-
-            >>> agnostic_dt_nanosecond(df_pd)
-                             datetime  nanosecond
-            0 1978-01-01 01:01:01.000           0
-            1 2024-10-13 05:30:14.500   500000000
-            2 2065-01-01 10:20:30.060    60000000
-
-            >>> agnostic_dt_nanosecond(df_pl)
-            shape: (3, 2)
-            ┌─────────────────────────┬────────────┐
-            │ datetime                ┆ nanosecond │
-            │ ---                     ┆ ---        │
-            │ datetime[μs]            ┆ i32        │
-            ╞═════════════════════════╪════════════╡
-            │ 1978-01-01 01:01:01     ┆ 0          │
-            │ 2024-10-13 05:30:14.500 ┆ 500000000  │
-            │ 2065-01-01 10:20:30.060 ┆ 60000000   │
-            └─────────────────────────┴────────────┘
-
-            >>> agnostic_dt_nanosecond(df_pa)
+            >>> df_native = pa.table(
+            ...     {
+            ...         "a": [
+            ...             datetime(1978, 1, 1, 1, 1, 1, 0),
+            ...             datetime(2065, 1, 1, 10, 20, 30, 67000),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     nw.col("a").dt.nanosecond().alias("nanosecond")
+            ... ).to_native()
             pyarrow.Table
-            datetime: timestamp[us]
+            a: timestamp[us]
             nanosecond: int64
             ----
-            datetime: [[1978-01-01 01:01:01.000000,2024-10-13 05:30:14.500000,2065-01-01 10:20:30.060000]]
-            nanosecond: [[0,500000000,60000000]]
+            a: [[1978-01-01 01:01:01.000000,2065-01-01 10:20:30.067000]]
+            nanosecond: [[0,67000000]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.nanosecond(),
@@ -695,50 +335,19 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import datetime
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"a": [datetime(2020, 1, 1), datetime(2020, 8, 3)]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_ordinal_day(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         a_ordinal_day=nw.col("a").dt.ordinal_day()
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_ordinal_day`:
-
-            >>> agnostic_dt_ordinal_day(df_pd)
-                       a  a_ordinal_day
-            0 2020-01-01              1
-            1 2020-08-03            216
-
-            >>> agnostic_dt_ordinal_day(df_pl)
-            shape: (2, 2)
-            ┌─────────────────────┬───────────────┐
-            │ a                   ┆ a_ordinal_day │
-            │ ---                 ┆ ---           │
-            │ datetime[μs]        ┆ i16           │
-            ╞═════════════════════╪═══════════════╡
-            │ 2020-01-01 00:00:00 ┆ 1             │
-            │ 2020-08-03 00:00:00 ┆ 216           │
-            └─────────────────────┴───────────────┘
-
-            >>> agnostic_dt_ordinal_day(df_pa)
-            pyarrow.Table
-            a: timestamp[us]
-            a_ordinal_day: int64
-            ----
-            a: [[2020-01-01 00:00:00.000000,2020-08-03 00:00:00.000000]]
-            a_ordinal_day: [[1,216]]
+            >>> df_native = pd.DataFrame(
+            ...     {"a": [datetime(2020, 1, 1), datetime(2020, 8, 3)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(a_ordinal_day=nw.col("a").dt.ordinal_day())
+            ┌───────────────────────────┐
+            |    Narwhals DataFrame     |
+            |---------------------------|
+            |           a  a_ordinal_day|
+            |0 2020-01-01              1|
+            |1 2020-08-03            216|
+            └───────────────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.ordinal_day(),
@@ -754,48 +363,19 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import datetime
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"a": [datetime(2020, 1, 1), datetime(2020, 8, 3)]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_weekday(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(a_weekday=nw.col("a").dt.weekday()).to_native()
-
-            We can then pass either pandas, Polars, PyArrow, and other supported libraries to
-            `agnostic_dt_weekday`:
-
-            >>> agnostic_dt_weekday(df_pd)
-                       a  a_weekday
-            0 2020-01-01          3
-            1 2020-08-03          1
-
-            >>> agnostic_dt_weekday(df_pl)
-            shape: (2, 2)
-            ┌─────────────────────┬───────────┐
-            │ a                   ┆ a_weekday │
-            │ ---                 ┆ ---       │
-            │ datetime[μs]        ┆ i8        │
-            ╞═════════════════════╪═══════════╡
-            │ 2020-01-01 00:00:00 ┆ 3         │
-            │ 2020-08-03 00:00:00 ┆ 1         │
-            └─────────────────────┴───────────┘
-
-            >>> agnostic_dt_weekday(df_pa)
-            pyarrow.Table
-            a: timestamp[us]
-            a_weekday: int64
-            ----
-            a: [[2020-01-01 00:00:00.000000,2020-08-03 00:00:00.000000]]
-            a_weekday: [[3,1]]
+            >>> df_native = pd.DataFrame(
+            ...     {"a": [datetime(2020, 1, 1), datetime(2020, 8, 3)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(a_week_day=nw.col("a").dt.weekday())
+            ┌────────────────────────┐
+            |   Narwhals DataFrame   |
+            |------------------------|
+            |           a  a_week_day|
+            |0 2020-01-01           3|
+            |1 2020-08-03           1|
+            └────────────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.weekday(),
@@ -815,34 +395,15 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import timedelta
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"a": [timedelta(minutes=10), timedelta(minutes=20, seconds=40)]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_total_minutes(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         a_total_minutes=nw.col("a").dt.total_minutes()
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_total_minutes`:
-
-            >>> agnostic_dt_total_minutes(df_pd)
-                            a  a_total_minutes
-            0 0 days 00:10:00               10
-            1 0 days 00:20:40               20
-
-            >>> agnostic_dt_total_minutes(df_pl)
+            >>> df_native = pl.DataFrame(
+            ...     {"a": [timedelta(minutes=10), timedelta(minutes=20, seconds=40)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     a_total_minutes=nw.col("a").dt.total_minutes()
+            ... ).to_native()
             shape: (2, 2)
             ┌──────────────┬─────────────────┐
             │ a            ┆ a_total_minutes │
@@ -852,14 +413,6 @@ class ExprDateTimeNamespace(Generic[ExprT]):
             │ 10m          ┆ 10              │
             │ 20m 40s      ┆ 20              │
             └──────────────┴─────────────────┘
-
-            >>> agnostic_dt_total_minutes(df_pa)
-            pyarrow.Table
-            a: duration[us]
-            a_total_minutes: int64
-            ----
-            a: [[600000000,1240000000]]
-            a_total_minutes: [[10,20]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.total_minutes(),
@@ -879,36 +432,15 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import timedelta
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [timedelta(seconds=10), timedelta(seconds=20, milliseconds=40)]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_total_seconds(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         a_total_seconds=nw.col("a").dt.total_seconds()
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_total_seconds`:
-
-            >>> agnostic_dt_total_seconds(df_pd)
-                                   a  a_total_seconds
-            0        0 days 00:00:10               10
-            1 0 days 00:00:20.040000               20
-
-            >>> agnostic_dt_total_seconds(df_pl)
+            >>> df_native = pl.DataFrame(
+            ...     {"a": [timedelta(seconds=10), timedelta(seconds=20, milliseconds=40)]}
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     a_total_seconds=nw.col("a").dt.total_seconds()
+            ... ).to_native()
             shape: (2, 2)
             ┌──────────────┬─────────────────┐
             │ a            ┆ a_total_seconds │
@@ -918,14 +450,6 @@ class ExprDateTimeNamespace(Generic[ExprT]):
             │ 10s          ┆ 10              │
             │ 20s 40ms     ┆ 20              │
             └──────────────┴─────────────────┘
-
-            >>> agnostic_dt_total_seconds(df_pa)
-            pyarrow.Table
-            a: duration[us]
-            a_total_seconds: int64
-            ----
-            a: [[10000000,20040000]]
-            a_total_seconds: [[10,20]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.total_seconds(),
@@ -945,39 +469,20 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import timedelta
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [
-            ...         timedelta(milliseconds=10),
-            ...         timedelta(milliseconds=20, microseconds=40),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_total_milliseconds(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         a_total_milliseconds=nw.col("a").dt.total_milliseconds()
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_total_milliseconds`:
-
-            >>> agnostic_dt_total_milliseconds(df_pd)
-                                   a  a_total_milliseconds
-            0 0 days 00:00:00.010000                    10
-            1 0 days 00:00:00.020040                    20
-
-            >>> agnostic_dt_total_milliseconds(df_pl)
+            >>> df_native = pl.DataFrame(
+            ...     {
+            ...         "a": [
+            ...             timedelta(milliseconds=10),
+            ...             timedelta(milliseconds=20, microseconds=40),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     a_total_milliseconds=nw.col("a").dt.total_milliseconds()
+            ... ).to_native()
             shape: (2, 2)
             ┌──────────────┬──────────────────────┐
             │ a            ┆ a_total_milliseconds │
@@ -987,14 +492,6 @@ class ExprDateTimeNamespace(Generic[ExprT]):
             │ 10ms         ┆ 10                   │
             │ 20040µs      ┆ 20                   │
             └──────────────┴──────────────────────┘
-
-            >>> agnostic_dt_total_milliseconds(df_pa)
-            pyarrow.Table
-            a: duration[us]
-            a_total_milliseconds: int64
-            ----
-            a: [[10000,20040]]
-            a_total_milliseconds: [[10,20]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.total_milliseconds(),
@@ -1014,50 +511,20 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import timedelta
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [
-            ...         timedelta(microseconds=10),
-            ...         timedelta(milliseconds=1, microseconds=200),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_total_microseconds(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         a_total_microseconds=nw.col("a").dt.total_microseconds()
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_total_microseconds`:
-
-            >>> agnostic_dt_total_microseconds(df_pd)
-                                   a  a_total_microseconds
-            0 0 days 00:00:00.000010                    10
-            1 0 days 00:00:00.001200                  1200
-
-            >>> agnostic_dt_total_microseconds(df_pl)
-            shape: (2, 2)
-            ┌──────────────┬──────────────────────┐
-            │ a            ┆ a_total_microseconds │
-            │ ---          ┆ ---                  │
-            │ duration[μs] ┆ i64                  │
-            ╞══════════════╪══════════════════════╡
-            │ 10µs         ┆ 10                   │
-            │ 1200µs       ┆ 1200                 │
-            └──────────────┴──────────────────────┘
-
-            >>> agnostic_dt_total_microseconds(df_pa)
+            >>> df_native = pa.table(
+            ...     {
+            ...         "a": [
+            ...             timedelta(microseconds=10),
+            ...             timedelta(milliseconds=1, microseconds=200),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     a_total_microseconds=nw.col("a").dt.total_microseconds()
+            ... ).to_native()
             pyarrow.Table
             a: duration[us]
             a_total_microseconds: int64
@@ -1084,42 +551,24 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import timedelta
             >>> import pandas as pd
-            >>> import polars as pl
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = ["2024-01-01 00:00:00.000000001", "2024-01-01 00:00:00.000000002"]
-            >>> df_pd = pd.DataFrame({"a": pd.to_datetime(data)})
-            >>> df_pl = pl.DataFrame({"a": data}).with_columns(
-            ...     pl.col("a").str.to_datetime(time_unit="ns")
+            >>> df_native = pd.DataFrame(
+            ...     {
+            ...         "a": pd.to_datetime(
+            ...             [
+            ...                 "2024-01-01 00:00:00.000000001",
+            ...                 "2024-01-01 00:00:00.000000002",
+            ...             ]
+            ...         )
+            ...     }
             ... )
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_total_nanoseconds(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         a_diff_total_nanoseconds=nw.col("a").diff().dt.total_nanoseconds()
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_total_nanoseconds`:
-
-            >>> agnostic_dt_total_nanoseconds(df_pd)
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(
+            ...     a_diff_total_nanoseconds=nw.col("a").diff().dt.total_nanoseconds()
+            ... ).to_native()
                                           a  a_diff_total_nanoseconds
             0 2024-01-01 00:00:00.000000001                       NaN
             1 2024-01-01 00:00:00.000000002                       1.0
-
-            >>> agnostic_dt_total_nanoseconds(df_pl)
-            shape: (2, 2)
-            ┌───────────────────────────────┬──────────────────────────┐
-            │ a                             ┆ a_diff_total_nanoseconds │
-            │ ---                           ┆ ---                      │
-            │ datetime[ns]                  ┆ i64                      │
-            ╞═══════════════════════════════╪══════════════════════════╡
-            │ 2024-01-01 00:00:00.000000001 ┆ null                     │
-            │ 2024-01-01 00:00:00.000000002 ┆ 1                        │
-            └───────────────────────────────┴──────────────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.total_nanoseconds(),
@@ -1168,57 +617,31 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import datetime
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [
-            ...         datetime(2020, 3, 1),
-            ...         datetime(2020, 4, 1),
-            ...         datetime(2020, 5, 1),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_to_string(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(
-            ...         nw.col("a").dt.to_string("%Y/%m/%d %H:%M:%S")
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_to_string`:
-
-            >>> agnostic_dt_to_string(df_pd)
-                                 a
-            0  2020/03/01 00:00:00
-            1  2020/04/01 00:00:00
-            2  2020/05/01 00:00:00
-
-            >>> agnostic_dt_to_string(df_pl)
-            shape: (3, 1)
-            ┌─────────────────────┐
-            │ a                   │
-            │ ---                 │
-            │ str                 │
-            ╞═════════════════════╡
-            │ 2020/03/01 00:00:00 │
-            │ 2020/04/01 00:00:00 │
-            │ 2020/05/01 00:00:00 │
-            └─────────────────────┘
-
-            >>> agnostic_dt_to_string(df_pa)
-            pyarrow.Table
-            a: string
-            ----
-            a: [["2020/03/01 00:00:00.000000","2020/04/01 00:00:00.000000","2020/05/01 00:00:00.000000"]]
+            >>> df_native = pl.DataFrame(
+            ...     {
+            ...         "a": [
+            ...             datetime(2020, 3, 1),
+            ...             datetime(2020, 5, 1),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("a").dt.to_string("%Y/%m/%d %H:%M:%S"))
+            ┌───────────────────────┐
+            |  Narwhals DataFrame   |
+            |-----------------------|
+            |shape: (2, 1)          |
+            |┌─────────────────────┐|
+            |│ a                   │|
+            |│ ---                 │|
+            |│ str                 │|
+            |╞═════════════════════╡|
+            |│ 2020/03/01 00:00:00 │|
+            |│ 2020/05/01 00:00:00 │|
+            |└─────────────────────┘|
+            └───────────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.to_string(format),
@@ -1237,53 +660,20 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import datetime, timezone
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [
-            ...         datetime(2024, 1, 1, tzinfo=timezone.utc),
-            ...         datetime(2024, 1, 2, tzinfo=timezone.utc),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            Let's define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_replace_time_zone(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(
-            ...         nw.col("a").dt.replace_time_zone("Asia/Kathmandu")
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_replace_time_zone`:
-
-            >>> agnostic_dt_replace_time_zone(df_pd)
+            >>> df_native = pd.DataFrame(
+            ...     {
+            ...         "a": [
+            ...             datetime(2024, 1, 1, tzinfo=timezone.utc),
+            ...             datetime(2024, 1, 2, tzinfo=timezone.utc),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")).to_native()
                                       a
             0 2024-01-01 00:00:00+05:45
             1 2024-01-02 00:00:00+05:45
-
-            >>> agnostic_dt_replace_time_zone(df_pl)
-            shape: (2, 1)
-            ┌──────────────────────────────┐
-            │ a                            │
-            │ ---                          │
-            │ datetime[μs, Asia/Kathmandu] │
-            ╞══════════════════════════════╡
-            │ 2024-01-01 00:00:00 +0545    │
-            │ 2024-01-02 00:00:00 +0545    │
-            └──────────────────────────────┘
-
-            >>> agnostic_dt_replace_time_zone(df_pa)
-            pyarrow.Table
-            a: timestamp[us, tz=Asia/Kathmandu]
-            ----
-            a: [[2023-12-31 18:15:00.000000Z,2024-01-01 18:15:00.000000Z]]
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).dt.replace_time_zone(
@@ -1307,53 +697,20 @@ class ExprDateTimeNamespace(Generic[ExprT]):
         Examples:
             >>> from datetime import datetime, timezone
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {
-            ...     "a": [
-            ...         datetime(2024, 1, 1, tzinfo=timezone.utc),
-            ...         datetime(2024, 1, 2, tzinfo=timezone.utc),
-            ...     ]
-            ... }
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            Let's define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_convert_time_zone(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(
-            ...         nw.col("a").dt.convert_time_zone("Asia/Kathmandu")
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_convert_time_zone`:
-
-            >>> agnostic_dt_convert_time_zone(df_pd)
+            >>> df_native = pd.DataFrame(
+            ...     {
+            ...         "a": [
+            ...             datetime(2024, 1, 1, tzinfo=timezone.utc),
+            ...             datetime(2024, 1, 2, tzinfo=timezone.utc),
+            ...         ]
+            ...     }
+            ... )
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("a").dt.convert_time_zone("Asia/Kathmandu")).to_native()
                                       a
             0 2024-01-01 05:45:00+05:45
             1 2024-01-02 05:45:00+05:45
-
-            >>> agnostic_dt_convert_time_zone(df_pl)
-            shape: (2, 1)
-            ┌──────────────────────────────┐
-            │ a                            │
-            │ ---                          │
-            │ datetime[μs, Asia/Kathmandu] │
-            ╞══════════════════════════════╡
-            │ 2024-01-01 05:45:00 +0545    │
-            │ 2024-01-02 05:45:00 +0545    │
-            └──────────────────────────────┘
-
-            >>> agnostic_dt_convert_time_zone(df_pa)
-            pyarrow.Table
-            a: timestamp[us, tz=Asia/Kathmandu]
-            ----
-            a: [[2024-01-01 00:00:00.000000Z,2024-01-02 00:00:00.000000Z]]
         """
         if time_zone is None:
             msg = "Target `time_zone` cannot be `None` in `convert_time_zone`. Please use `replace_time_zone(None)` if you want to remove the time zone."
@@ -1377,56 +734,24 @@ class ExprDateTimeNamespace(Generic[ExprT]):
 
         Examples:
             >>> from datetime import date
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"date": [date(2001, 1, 1), None, date(2001, 1, 3)]}
-            >>> df_pd = pd.DataFrame(data, dtype="datetime64[ns]")
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            Let's define a dataframe-agnostic function:
-
-            >>> def agnostic_dt_timestamp(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(
-            ...         nw.col("date").dt.timestamp().alias("timestamp_us"),
-            ...         nw.col("date").dt.timestamp("ms").alias("timestamp_ms"),
-            ...     ).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_dt_timestamp`:
-
-            >>> agnostic_dt_timestamp(df_pd)
-                    date  timestamp_us  timestamp_ms
-            0 2001-01-01  9.783072e+14  9.783072e+11
-            1        NaT           NaN           NaN
-            2 2001-01-03  9.784800e+14  9.784800e+11
-
-            >>> agnostic_dt_timestamp(df_pl)
-            shape: (3, 3)
-            ┌────────────┬─────────────────┬──────────────┐
-            │ date       ┆ timestamp_us    ┆ timestamp_ms │
-            │ ---        ┆ ---             ┆ ---          │
-            │ date       ┆ i64             ┆ i64          │
-            ╞════════════╪═════════════════╪══════════════╡
-            │ 2001-01-01 ┆ 978307200000000 ┆ 978307200000 │
-            │ null       ┆ null            ┆ null         │
-            │ 2001-01-03 ┆ 978480000000000 ┆ 978480000000 │
-            └────────────┴─────────────────┴──────────────┘
-
-            >>> agnostic_dt_timestamp(df_pa)
-            pyarrow.Table
-            date: date32[day]
-            timestamp_us: int64
-            timestamp_ms: int64
-            ----
-            date: [[2001-01-01,null,2001-01-03]]
-            timestamp_us: [[978307200000000,null,978480000000000]]
-            timestamp_ms: [[978307200000,null,978480000000]]
+            >>> df_native = pl.DataFrame({"date": [date(2001, 1, 1), None]})
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(nw.col("date").dt.timestamp("ms").alias("timestamp_ms"))
+            ┌─────────────────────────────┐
+            |     Narwhals DataFrame      |
+            |-----------------------------|
+            |shape: (2, 2)                |
+            |┌────────────┬──────────────┐|
+            |│ date       ┆ timestamp_ms │|
+            |│ ---        ┆ ---          │|
+            |│ date       ┆ i64          │|
+            |╞════════════╪══════════════╡|
+            |│ 2001-01-01 ┆ 978307200000 │|
+            |│ null       ┆ null         │|
+            |└────────────┴──────────────┘|
+            └─────────────────────────────┘
         """
         if time_unit not in {"ns", "us", "ms"}:
             msg = (
diff --git a/narwhals/expr_list.py b/narwhals/expr_list.py
index fc6a1227..593b5111 100644
--- a/narwhals/expr_list.py
+++ b/narwhals/expr_list.py
@@ -25,52 +25,26 @@ class ExprListNamespace(Generic[ExprT]):
             A new expression.
 
         Examples:
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"a": [[1, 2], [3, 4, None], None, []]}
-
-            Let's define a dataframe-agnostic function:
-
-            >>> def agnostic_list_len(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.with_columns(a_len=nw.col("a").list.len()).to_native()
-
-            We can then pass pandas / PyArrow / Polars / any other supported library:
-
-            >>> agnostic_list_len(
-            ...     pd.DataFrame(data).astype({"a": pd.ArrowDtype(pa.list_(pa.int64()))})
-            ... )  # doctest: +SKIP
-                           a  a_len
-            0        [1. 2.]      2
-            1  [ 3.  4. nan]      3
-            2           <NA>   <NA>
-            3             []      0
-
-            >>> agnostic_list_len(pl.DataFrame(data))
-            shape: (4, 2)
-            ┌──────────────┬───────┐
-            │ a            ┆ a_len │
-            │ ---          ┆ ---   │
-            │ list[i64]    ┆ u32   │
-            ╞══════════════╪═══════╡
-            │ [1, 2]       ┆ 2     │
-            │ [3, 4, null] ┆ 3     │
-            │ null         ┆ null  │
-            │ []           ┆ 0     │
-            └──────────────┴───────┘
-
-            >>> agnostic_list_len(pa.table(data))
-            pyarrow.Table
-            a: list<item: int64>
-              child 0, item: int64
-            a_len: uint32
-            ----
-            a: [[[1,2],[3,4,null],null,[]]]
-            a_len: [[2,3,null,0]]
+            >>> df_native = pl.DataFrame({"a": [[1, 2], [3, 4, None], None, []]})
+            >>> df = nw.from_native(df_native)
+            >>> df.with_columns(a_len=nw.col("a").list.len())
+            ┌────────────────────────┐
+            |   Narwhals DataFrame   |
+            |------------------------|
+            |shape: (4, 2)           |
+            |┌──────────────┬───────┐|
+            |│ a            ┆ a_len │|
+            |│ ---          ┆ ---   │|
+            |│ list[i64]    ┆ u32   │|
+            |╞══════════════╪═══════╡|
+            |│ [1, 2]       ┆ 2     │|
+            |│ [3, 4, null] ┆ 3     │|
+            |│ null         ┆ null  │|
+            |│ []           ┆ 0     │|
+            |└──────────────┴───────┘|
+            └────────────────────────┘
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).list.len(),
diff --git a/narwhals/expr_name.py b/narwhals/expr_name.py
index fbf8c86f..58ac9025 100644
--- a/narwhals/expr_name.py
+++ b/narwhals/expr_name.py
@@ -30,34 +30,10 @@ class ExprNameNamespace(Generic[ExprT]):
 
         Examples:
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrame
-            >>>
-            >>> data = {"foo": [1, 2], "BAR": [4, 5]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_name_keep(df_native: IntoFrame) -> list[str]:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(
-            ...         nw.col("foo").alias("alias_for_foo").name.keep()
-            ...     ).columns
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_name_keep`:
-
-            >>> agnostic_name_keep(df_pd)
-            ['foo']
-
-            >>> agnostic_name_keep(df_pl)
-            ['foo']
-
-            >>> agnostic_name_keep(df_pa)
+            >>> df_native = pd.DataFrame({"foo": [1, 2], "BAR": [4, 5]})
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("foo").alias("alias_for_foo").name.keep()).columns
             ['foo']
         """
         return self._expr.__class__(
@@ -81,33 +57,11 @@ class ExprNameNamespace(Generic[ExprT]):
 
         Examples:
             >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrame
-            >>>
-            >>> data = {"foo": [1, 2], "BAR": [4, 5]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
+            >>> df_native = pd.DataFrame({"foo": [1, 2], "BAR": [4, 5]})
+            >>> df = nw.from_native(df_native)
             >>> renaming_func = lambda s: s[::-1]  # reverse column name
-            >>> def agnostic_name_map(df_native: IntoFrame) -> list[str]:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("foo", "BAR").name.map(renaming_func)).columns
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_name_map`:
-
-            >>> agnostic_name_map(df_pd)
-            ['oof', 'RAB']
-
-            >>> agnostic_name_map(df_pl)
-            ['oof', 'RAB']
-
-            >>> agnostic_name_map(df_pa)
+            >>> df.select(nw.col("foo", "BAR").name.map(renaming_func)).columns
             ['oof', 'RAB']
         """
         return self._expr.__class__(
@@ -130,34 +84,12 @@ class ExprNameNamespace(Generic[ExprT]):
             expression in a chain. Only one name operation per expression will work.
 
         Examples:
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrame
-            >>>
-            >>> data = {"foo": [1, 2], "BAR": [4, 5]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_name_prefix(df_native: IntoFrame, prefix: str) -> list[str]:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("foo", "BAR").name.prefix(prefix)).columns
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_name_prefix`:
-
-            >>> agnostic_name_prefix(df_pd, "with_prefix_")
-            ['with_prefix_foo', 'with_prefix_BAR']
-
-            >>> agnostic_name_prefix(df_pl, "with_prefix_")
-            ['with_prefix_foo', 'with_prefix_BAR']
-
-            >>> agnostic_name_prefix(df_pa, "with_prefix_")
-            ['with_prefix_foo', 'with_prefix_BAR']
+            >>> df_native = pl.DataFrame({"foo": [1, 2], "BAR": [4, 5]})
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("foo", "BAR").name.prefix("with_prefix")).columns
+            ['with_prefixfoo', 'with_prefixBAR']
         """
         return self._expr.__class__(
             lambda plx: self._expr._to_compliant_expr(plx).name.prefix(prefix),
@@ -179,33 +111,11 @@ class ExprNameNamespace(Generic[ExprT]):
             expression in a chain. Only one name operation per expression will work.
 
         Examples:
-            >>> import pandas as pd
             >>> import polars as pl
-            >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrame
-            >>>
-            >>> data = {"foo": [1, 2], "BAR": [4, 5]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_name_suffix(df_native: IntoFrame, suffix: str) -> list[str]:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("foo", "BAR").name.suffix(suffix)).columns
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_name_suffix`:
-
-            >>> agnostic_name_suffix(df_pd, "_with_suffix")
-            ['foo_with_suffix', 'BAR_with_suffix']
-
-            >>> agnostic_name_suffix(df_pl, "_with_suffix")
-            ['foo_with_suffix', 'BAR_with_suffix']
-
-            >>> agnostic_name_suffix(df_pa, "_with_suffix")
+            >>> df_native = pl.DataFrame({"foo": [1, 2], "BAR": [4, 5]})
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("foo", "BAR").name.suffix("_with_suffix")).columns
             ['foo_with_suffix', 'BAR_with_suffix']
         """
         return self._expr.__class__(
@@ -225,33 +135,11 @@ class ExprNameNamespace(Generic[ExprT]):
             expression in a chain. Only one name operation per expression will work.
 
         Examples:
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrame
-            >>>
-            >>> data = {"foo": [1, 2], "BAR": [4, 5]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_name_to_lowercase(df_native: IntoFrame) -> list[str]:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("foo", "BAR").name.to_lowercase()).columns
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_name_to_lowercase`:
-
-            >>> agnostic_name_to_lowercase(df_pd)
-            ['foo', 'bar']
-
-            >>> agnostic_name_to_lowercase(df_pl)
-            ['foo', 'bar']
-
-            >>> agnostic_name_to_lowercase(df_pa)
+            >>> df_native = pa.table({"foo": [1, 2], "BAR": [4, 5]})
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("foo", "BAR").name.to_lowercase()).columns
             ['foo', 'bar']
         """
         return self._expr.__class__(
@@ -271,33 +159,11 @@ class ExprNameNamespace(Generic[ExprT]):
             expression in a chain. Only one name operation per expression will work.
 
         Examples:
-            >>> import pandas as pd
-            >>> import polars as pl
             >>> import pyarrow as pa
             >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrame
-            >>>
-            >>> data = {"foo": [1, 2], "BAR": [4, 5]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a dataframe-agnostic function:
-
-            >>> def agnostic_name_to_uppercase(df_native: IntoFrame) -> list[str]:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("foo", "BAR").name.to_uppercase()).columns
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_name_to_uppercase`:
-
-            >>> agnostic_name_to_uppercase(df_pd)
-            ['FOO', 'BAR']
-
-            >>> agnostic_name_to_uppercase(df_pl)
-            ['FOO', 'BAR']
-
-            >>> agnostic_name_to_uppercase(df_pa)
+            >>> df_native = pa.table({"foo": [1, 2], "BAR": [4, 5]})
+            >>> df = nw.from_native(df_native)
+            >>> df.select(nw.col("foo", "BAR").name.to_uppercase()).columns
             ['FOO', 'BAR']
         """
         return self._expr.__class__(
diff --git a/narwhals/expr_str.py b/narwhals/expr_str.py
index 83b4e20e..92060096 100644
--- a/narwhals/expr_str.py
+++ b/narwhals/expr_str.py
@@ -250,7 +250,7 @@ class ExprStringNamespace(Generic[ExprT]):
             A new expression.
 
         Examples:
-           >>> import pandas as pd
+            >>> import pandas as pd
             >>> import narwhals as nw
             >>> df_native = pd.DataFrame({"s": ["pear", None, "papaya"]})
             >>> df = nw.from_native(df_native)
diff --git a/narwhals/functions.py b/narwhals/functions.py
index 5e80e05c..e1f85f5d 100644
--- a/narwhals/functions.py
+++ b/narwhals/functions.py
@@ -1040,6 +1040,43 @@ def col(*names: str | Iterable[str]) -> Expr:
     return Expr(func, ExprMetadata.selector())
 
 
+def exclude(*names: str | Iterable[str]) -> Expr:
+    """Creates an expression that excludes columns by their name(s).
+
+    Arguments:
+        names: Name(s) of the columns to exclude.
+
+    Returns:
+        A new expression.
+
+    Examples:
+        >>> import polars as pl
+        >>> import narwhals as nw
+        >>>
+        >>> df_native = pl.DataFrame({"a": [1, 2], "b": [3, 4], "c": ["x", "z"]})
+        >>> nw.from_native(df_native).select(nw.exclude("c", "a"))
+        ┌──────────────────┐
+        |Narwhals DataFrame|
+        |------------------|
+        |  shape: (2, 1)   |
+        |  ┌─────┐         |
+        |  │ b   │         |
+        |  │ --- │         |
+        |  │ i64 │         |
+        |  ╞═════╡         |
+        |  │ 3   │         |
+        |  │ 4   │         |
+        |  └─────┘         |
+        └──────────────────┘
+    """
+    exclude_names = frozenset(flatten(names))
+
+    def func(plx: Any) -> Any:
+        return plx.exclude(exclude_names)
+
+    return Expr(func, ExprMetadata.selector())
+
+
 def nth(*indices: int | Sequence[int]) -> Expr:
     """Creates an expression that references one or more columns by their index(es).
 
diff --git a/narwhals/stable/v1/__init__.py b/narwhals/stable/v1/__init__.py
index 8a0e2b13..fbdc9351 100644
--- a/narwhals/stable/v1/__init__.py
+++ b/narwhals/stable/v1/__init__.py
@@ -1826,6 +1826,18 @@ def col(*names: str | Iterable[str]) -> Expr:
     return _stableify(nw.col(*names))
 
 
+def exclude(*names: str | Iterable[str]) -> Expr:
+    """Creates an expression that excludes columns by their name(s).
+
+    Arguments:
+        names: Name(s) of the columns to exclude.
+
+    Returns:
+        A new expression.
+    """
+    return _stableify(nw.exclude(*names))
+
+
 def nth(*indices: int | Sequence[int]) -> Expr:
     """Creates an expression that references one or more columns by their index(es).
 
@@ -2417,6 +2429,7 @@ __all__ = [
     "dependencies",
     "dtypes",
     "exceptions",
+    "exclude",
     "from_arrow",
     "from_dict",
     "from_native",


Test patch:
diff --git a/tests/expr_and_series/exclude_test.py b/tests/expr_and_series/exclude_test.py
new file mode 100644
index 00000000..a6679faa
--- /dev/null
+++ b/tests/expr_and_series/exclude_test.py
@@ -0,0 +1,32 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+import pytest
+
+import narwhals.stable.v1 as nw
+from tests.utils import assert_equal_data
+
+if TYPE_CHECKING:
+    from tests.utils import Constructor
+
+
+@pytest.mark.parametrize(
+    ("exclude_selector", "expected_cols"),
+    [
+        (nw.exclude("a"), ["b", "z"]),
+        (nw.exclude("b", "z"), ["a"]),
+        (nw.exclude(["a"]), ["b", "z"]),
+        (nw.exclude(["b", "z"]), ["a"]),
+    ],
+)
+def test_exclude(
+    constructor: Constructor, exclude_selector: nw.Expr, expected_cols: list[str]
+) -> None:
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
+
+    df = nw.from_native(constructor(data))
+    result = df.select(exclude_selector)
+
+    expected = {col: data[col] for col in expected_cols}
+    assert_equal_data(result, expected)