def setattr(
        self,
        target: str | object,
        name: object | str,
        value: object = notset,
        raising: bool = True,
    ) -> None:
        """
        Set attribute value on target, memorizing the old value.

        For example:

        .. code-block:: python

            import os

            monkeypatch.setattr(os, "getcwd", lambda: "/")

        The code above replaces the :func:`os.getcwd` function by a ``lambda`` which
        always returns ``"/"``.

        For convenience, you can specify a string as ``target`` which
        will be interpreted as a dotted import path, with the last part
        being the attribute name:

        .. code-block:: python

            monkeypatch.setattr("os.getcwd", lambda: "/")

        Raises :class:`AttributeError` if the attribute does not exist, unless
        ``raising`` is set to False.

        **Where to patch**

        ``monkeypatch.setattr`` works by (temporarily) changing the object that a name points to with another one.
        There can be many names pointing to any individual object, so for patching to work you must ensure
        that you patch the name used by the system under test.

        See the section :ref:`Where to patch <python:where-to-patch>` in the :mod:`unittest.mock`
        docs for a complete explanation, which is meant for :func:`unittest.mock.patch` but
        applies to ``monkeypatch.setattr`` as well.
        """
        __tracebackhide__ = True
        import inspect

        if isinstance(value, Notset):
            if not isinstance(target, str):
                raise TypeError(
                    "use setattr(target, name, value) or "
                    "setattr(target, value) with target being a dotted "
                    "import string"
                )
            value = name
            name, target = derive_importpath(target, raising)
        else:
            if not isinstance(name, str):
                raise TypeError(
                    "use setattr(target, name, value) with name being a string or "
                    "setattr(target, value) with target being a dotted "
                    "import string"
                )

        oldval = getattr(target, name, notset)
        if raising and oldval is notset:
            raise AttributeError(f"{target!r} has no attribute {name!r}")

        # avoid class descriptors like staticmethod/classmethod
        if inspect.isclass(target):
            oldval = target.__dict__.get(name, notset)
        self._setattr.append((target, name, oldval))
        setattr(target, name, value)

        Set attribute value on target, memorizing the old value.

        For example:

        .. code-block:: python

            import os

            monkeypatch.setattr(os, "getcwd", lambda: "/")

        The code above replaces the :func:`os.getcwd` function by a ``lambda`` which
        always returns ``"/"``.

        For convenience, you can specify a string as ``target`` which
        will be interpreted as a dotted import path, with the last part
        being the attribute name:

        .. code-block:: python

            monkeypatch.setattr("os.getcwd", lambda: "/")

        Raises :class:`AttributeError` if the attribute does not exist, unless
        ``raising`` is set to False.

        **Where to patch**

        ``monkeypatch.setattr`` works by (temporarily) changing the object that a name points to with another one.
        There can be many names pointing to any individual object, so for patching to work you must ensure
        that you patch the name used by the system under test.

        See the section :ref:`Where to patch <python:where-to-patch>` in the :mod:`unittest.mock`
        docs for a complete explanation, which is meant for :func:`unittest.mock.patch` but
        applies to ``monkeypatch.setattr`` as well.
        
src/_pytest/monkeypatch.py