def iterrows(self) -> Iterator[Tuple[(Name, pd.Series)]]:
    "\n        Iterate over DataFrame rows as (index, Series) pairs.\n\n        Yields\n        ------\n        index : label or tuple of label\n            The index of the row. A tuple for a `MultiIndex`.\n        data : pandas.Series\n            The data of the row as a Series.\n\n        it : generator\n            A generator that iterates over the rows of the frame.\n\n        Notes\n        -----\n\n        1. Because ``iterrows`` returns a Series for each row,\n           it does **not** preserve dtypes across the rows (dtypes are\n           preserved across columns for DataFrames). For example,\n\n           >>> df = ps.DataFrame([[1, 1.5]], columns=['int', 'float'])\n           >>> row = next(df.iterrows())[1]\n           >>> row\n           int      1.0\n           float    1.5\n           Name: 0, dtype: float64\n           >>> print(row['int'].dtype)\n           float64\n           >>> print(df['int'].dtype)\n           int64\n\n           To preserve dtypes while iterating over the rows, it is better\n           to use :meth:`itertuples` which returns namedtuples of the values\n           and which is generally faster than ``iterrows``.\n\n        2. You should **never modify** something you are iterating over.\n           This is not guaranteed to work in all cases. Depending on the\n           data types, the iterator returns a copy and not a view, and writing\n           to it will have no effect.\n        "
    columns = self.columns
    internal_index_columns = self._internal.index_spark_column_names
    internal_data_columns = self._internal.data_spark_column_names

    def extract_kv_from_spark_row(row: Row) -> Tuple[(Name, Any)]:
        k = (row[internal_index_columns[0]] if (len(internal_index_columns) == 1) else tuple((row[c] for c in internal_index_columns)))
        v = [row[c] for c in internal_data_columns]
        return (k, v)
    for (k, v) in map(extract_kv_from_spark_row, self._internal.resolved_copy.spark_frame.toLocalIterator()):
        s = pd.Series(v, index=columns, name=k)
        (yield (k, s))
Iterate over DataFrame rows as (index, Series) pairs.

Yields
------
index : label or tuple of label
    The index of the row. A tuple for a `MultiIndex`.
data : pandas.Series
    The data of the row as a Series.

it : generator
    A generator that iterates over the rows of the frame.

Notes
-----

1. Because ``iterrows`` returns a Series for each row,
   it does **not** preserve dtypes across the rows (dtypes are
   preserved across columns for DataFrames). For example,

   >>> df = ps.DataFrame([[1, 1.5]], columns=['int', 'float'])
   >>> row = next(df.iterrows())[1]
   >>> row
   int      1.0
   float    1.5
   Name: 0, dtype: float64
   >>> print(row['int'].dtype)
   float64
   >>> print(df['int'].dtype)
   int64

   To preserve dtypes while iterating over the rows, it is better
   to use :meth:`itertuples` which returns namedtuples of the values
   and which is generally faster than ``iterrows``.

2. You should **never modify** something you are iterating over.
   This is not guaranteed to work in all cases. Depending on the
   data types, the iterator returns a copy and not a view, and writing
   to it will have no effect.
def iterrows(self) -> Iterator[Tuple[(Name, pd.Series)]]:
    "\n        Iterate over DataFrame rows as (index, Series) pairs.\n\n        Yields\n        ------\n        index : label or tuple of label\n            The index of the row. A tuple for a `MultiIndex`.\n        data : pandas.Series\n            The data of the row as a Series.\n\n        it : generator\n            A generator that iterates over the rows of the frame.\n\n        Notes\n        -----\n\n        1. Because ``iterrows`` returns a Series for each row,\n           it does **not** preserve dtypes across the rows (dtypes are\n           preserved across columns for DataFrames). For example,\n\n           >>> df = ps.DataFrame([[1, 1.5]], columns=['int', 'float'])\n           >>> row = next(df.iterrows())[1]\n           >>> row\n           int      1.0\n           float    1.5\n           Name: 0, dtype: float64\n           >>> print(row['int'].dtype)\n           float64\n           >>> print(df['int'].dtype)\n           int64\n\n           To preserve dtypes while iterating over the rows, it is better\n           to use :meth:`itertuples` which returns namedtuples of the values\n           and which is generally faster than ``iterrows``.\n\n        2. You should **never modify** something you are iterating over.\n           This is not guaranteed to work in all cases. Depending on the\n           data types, the iterator returns a copy and not a view, and writing\n           to it will have no effect.\n        "
    columns = self.columns
    internal_index_columns = self._internal.index_spark_column_names
    internal_data_columns = self._internal.data_spark_column_names

    def extract_kv_from_spark_row(row: Row) -> Tuple[(Name, Any)]:
        k = (row[internal_index_columns[0]] if (len(internal_index_columns) == 1) else tuple((row[c] for c in internal_index_columns)))
        v = [row[c] for c in internal_data_columns]
        return (k, v)
    for (k, v) in map(extract_kv_from_spark_row, self._internal.resolved_copy.spark_frame.toLocalIterator()):
        s = pd.Series(v, index=columns, name=k)
        (yield (k, s))