code: def node_degree_xy(G, x="out", y="in", weight=None, nodes=None):
      """Generate node degree-degree pairs for edges in G.
  
      Parameters
      ----------
      G: NetworkX graph
  
      x: string ('in','out')
         The degree type for source node (directed graphs only).
  
      y: string ('in','out')
         The degree type for target node (directed graphs only).
  
      weight: string or None, optional (default=None)
         The edge attribute that holds the numerical value used
         as a weight.  If None, then each edge has weight 1.
         The degree is the sum of the edge weights adjacent to the node.
  
      nodes: list or iterable (optional)
          Use only edges that are adjacency to specified nodes.
          The default is all nodes.
  
      Returns
      -------
      (x, y): 2-tuple
          Generates 2-tuple of (degree, degree) values.
  
  
      Examples
      --------
      >>> G = nx.DiGraph()
      >>> G.add_edge(1, 2)
      >>> list(nx.node_degree_xy(G, x="out", y="in"))
      [(1, 1)]
      >>> list(nx.node_degree_xy(G, x="in", y="out"))
      [(0, 0)]
  
      Notes
      -----
      For undirected graphs each edge is produced twice, once for each edge
      representation (u, v) and (v, u), with the exception of self-loop edges
      which only appear once.
      """
      nodes = set(G) if nodes is None else set(nodes)
      if G.is_directed():
          direction = {"out": G.out_degree, "in": G.in_degree}
          xdeg = direction[x]
          ydeg = direction[y]
      else:
          xdeg = ydeg = G.degree
  
      for u, degu in xdeg(nodes, weight=weight):
          # use G.edges to treat multigraphs correctly
          neighbors = (nbr for _, nbr in G.edges(u) if nbr in nodes)
          for _, degv in ydeg(neighbors, weight=weight):
              yield degu, degv
  
label_desc: Use image node_id 2 for calling a global function with example usage: node_degree_xy(G, x, y, weight, nodes) without return types