code: def delayed(obj, name=None, pure=None, nout=None, traverse=True):
      """Wraps a function or object to produce a ``Delayed``.
  
      ``Delayed`` objects act as proxies for the object they wrap, but all
      operations on them are done lazily by building up a dask graph internally.
  
      Parameters
      ----------
      obj : object
          The function or object to wrap
      name : Dask key, optional
          The key to use in the underlying graph for the wrapped object. Defaults
          to hashing content. Note that this only affects the name of the object
          wrapped by this call to delayed, and *not* the output of delayed
          function calls - for that use ``dask_key_name=`` as described below.
  
          .. note::
  
             Because this ``name`` is used as the key in task graphs, you should
             ensure that it uniquely identifies ``obj``. If you'd like to provide
             a descriptive name that is still unique, combine the descriptive name
             with :func:`dask.base.tokenize` of the ``array_like``. See
             :ref:`graphs` for more.
  
      pure : bool, optional
          Indicates whether calling the resulting ``Delayed`` object is a pure
          operation. If True, arguments to the call are hashed to produce
          deterministic keys. If not provided, the default is to check the global
          ``delayed_pure`` setting, and fallback to ``False`` if unset.
      nout : int, optional
          The number of outputs returned from calling the resulting ``Delayed``
          object. If provided, the ``Delayed`` output of the call can be iterated
          into ``nout`` objects, allowing for unpacking of results. By default
          iteration over ``Delayed`` objects will error. Note, that ``nout=1``
          expects ``obj`` to return a tuple of length 1, and consequently for
          ``nout=0``, ``obj`` should return an empty tuple.
      traverse : bool, optional
          By default dask traverses builtin python collections looking for dask
          objects passed to ``delayed``. For large collections this can be
          expensive. If ``obj`` doesn't contain any dask objects, set
          ``traverse=False`` to avoid doing this traversal.
  
      Examples
      --------
      Apply to functions to delay execution:
  
      >>> from dask import delayed
      >>> def inc(x):
      ...     return x + 1
  
      >>> inc(10)
      11
  
      >>> x = delayed(inc, pure=True)(10)
      >>> type(x) == Delayed
      True
      >>> x.compute()
      11
  
      Can be used as a decorator:
  
      >>> @delayed(pure=True)
      ... def add(a, b):
      ...     return a + b
      >>> add(1, 2).compute()
      3
  
      ``delayed`` also accepts an optional keyword ``pure``. If False, then
      subsequent calls will always produce a different ``Delayed``. This is
      useful for non-pure functions (such as ``time`` or ``random``).
  
      >>> from random import random
      >>> out1 = delayed(random, pure=False)()
      >>> out2 = delayed(random, pure=False)()
      >>> out1.key == out2.key
      False
  
      If you know a function is pure (output only depends on the input, with no
      global state), then you can set ``pure=True``. This will attempt to apply a
      consistent name to the output, but will fallback on the same behavior of
      ``pure=False`` if this fails.
  
      >>> @delayed(pure=True)
      ... def add(a, b):
      ...     return a + b
      >>> out1 = add(1, 2)
      >>> out2 = add(1, 2)
      >>> out1.key == out2.key
      True
  
      Instead of setting ``pure`` as a property of the callable, you can also set
      it contextually using the ``delayed_pure`` setting. Note that this
      influences the *call* and not the *creation* of the callable:
  
      >>> @delayed
      ... def mul(a, b):
      ...     return a * b
      >>> import dask
      >>> with dask.config.set(delayed_pure=True):
      ...     print(mul(1, 2).key == mul(1, 2).key)
      True
      >>> with dask.config.set(delayed_pure=False):
      ...     print(mul(1, 2).key == mul(1, 2).key)
      False
  
      The key name of the result of calling a delayed object is determined by
      hashing the arguments by default. To explicitly set the name, you can use
      the ``dask_key_name`` keyword when calling the function:
  
      >>> add(1, 2)   # doctest: +SKIP
      Delayed('add-3dce7c56edd1ac2614add714086e950f')
      >>> add(1, 2, dask_key_name='three')
      Delayed('three')
  
      Note that objects with the same key name are assumed to have the same
      result. If you set the names explicitly you should make sure your key names
      are different for different results.
  
      >>> add(1, 2, dask_key_name='three')
      Delayed('three')
      >>> add(2, 1, dask_key_name='three')
      Delayed('three')
      >>> add(2, 2, dask_key_name='four')
      Delayed('four')
  
      ``delayed`` can also be applied to objects to make operations on them lazy:
  
      >>> a = delayed([1, 2, 3])
      >>> isinstance(a, Delayed)
      True
      >>> a.compute()
      [1, 2, 3]
  
      The key name of a delayed object is hashed by default if ``pure=True`` or
      is generated randomly if ``pure=False`` (default).  To explicitly set the
      name, you can use the ``name`` keyword. To ensure that the key is unique
      you should include the tokenized value as well, or otherwise ensure that
      it's unique:
  
      >>> from dask.base import tokenize
      >>> data = [1, 2, 3]
      >>> a = delayed(data, name='mylist-' + tokenize(data))
      >>> a  # doctest: +SKIP
      Delayed('mylist-55af65871cb378a4fa6de1660c3e8fb7')
  
      Delayed results act as a proxy to the underlying object. Many operators
      are supported:
  
      >>> (a + [1, 2]).compute()
      [1, 2, 3, 1, 2]
      >>> a[1].compute()
      2
  
      Method and attribute access also works:
  
      >>> a.count(2).compute()
      1
  
      Note that if a method doesn't exist, no error will be thrown until runtime:
  
      >>> res = a.not_a_real_method() # doctest: +SKIP
      >>> res.compute()  # doctest: +SKIP
      AttributeError("'list' object has no attribute 'not_a_real_method'")
  
      "Magic" methods (e.g. operators and attribute access) are assumed to be
      pure, meaning that subsequent calls must return the same results. This
      behavior is not overrideable through the ``delayed`` call, but can be
      modified using other ways as described below.
  
      To invoke an impure attribute or operator, you'd need to use it in a
      delayed function with ``pure=False``:
  
      >>> class Incrementer:
      ...     def __init__(self):
      ...         self._n = 0
      ...     @property
      ...     def n(self):
      ...         self._n += 1
      ...         return self._n
      ...
      >>> x = delayed(Incrementer())
      >>> x.n.key == x.n.key
      True
      >>> get_n = delayed(lambda x: x.n, pure=False)
      >>> get_n(x).key == get_n(x).key
      False
  
      In contrast, methods are assumed to be impure by default, meaning that
      subsequent calls may return different results. To assume purity, set
      ``pure=True``. This allows sharing of any intermediate values.
  
      >>> a.count(2, pure=True).key == a.count(2, pure=True).key
      True
  
      As with function calls, method calls also respect the global
      ``delayed_pure`` setting and support the ``dask_key_name`` keyword:
  
      >>> a.count(2, dask_key_name="count_2")
      Delayed('count_2')
      >>> import dask
      >>> with dask.config.set(delayed_pure=True):
      ...     print(a.count(2).key == a.count(2).key)
      True
      """
      if isinstance(obj, Delayed):
          return obj
  
      if is_dask_collection(obj) or traverse:
          task, collections = unpack_collections(obj)
      else:
          task = quote(obj)
          collections = set()
  
      if not (nout is None or (type(nout) is int and nout >= 0)):
          raise ValueError(
              "nout must be None or a non-negative integer, got %s"
              % nout
          )
      if task is obj:
          if not name:
              try:
                  prefix = obj.__name__
              except AttributeError:
                  prefix = type(obj).__name__
              token = tokenize(obj, nout, pure=pure)
              name = f"{prefix}-{token}"
          return DelayedLeaf(obj, name, pure=pure, nout=nout)
      else:
          if not name:
              name = f"{type(obj).__name__}-{tokenize(task, pure=pure)}"
          layer = {name: task}
          graph = HighLevelGraph.from_collections(
              name, layer, dependencies=collections
          )
          return Delayed(name, graph, nout)
  
imports: from __future__ import annotations
  import operator
  import types
  import uuid
  import warnings
  from collections.abc import Sequence
  from dataclasses import fields, is_dataclass, replace
  from functools import partial
  from tlz import concat, curry, merge, unique
  from dask import config
  from dask.base import DaskMethodsMixin, dont_optimize, is_dask_collection, named_schedulers, replace_name_in_key
  from dask.base import tokenize
  from dask.context import globalmethod
  from dask.core import flatten, quote
  from dask.highlevelgraph import HighLevelGraph
  from dask.typing import Graph, NestedKeys
  from dask.utils import OperatorMethodMixin, apply, funcname, is_namedtuple_instance, methodcaller
label_desc: Use image node_id 6 for calling a global function with example usage: delayed(obj, name, pure, nout, traverse) and returns: obj, DelayedLeaf, Delayed