class_docstr: A plain python object modeling a heterogeneous graph with various
  attributes (Node types in :class:`HeteroGraph` require string type).
  
  Args:
      G (:class:`networkx.classes.graph`): A NetworkX graph object which
          contains features and labels for each node type and edge type.
      **kwargs: Keyworded argument list with keys such
          as :obj:`"node_feature"`, :obj:`"node_label"` and
          corresponding attributes.
class_docstr_tok: ["A","plain","python","object","modeling","a","heterogeneous","graph","with","various","attributes","(","Node","types","in",":","class",":","`","HeteroGraph","`","require","string","type",")",".","Args",":","G","(",":","class",":","`","networkx.classes.graph","`",")",":","A","NetworkX","graph","object","which","contains","features","and","labels","for","each","node","type","and","edge","type",".","*","*","kwargs",":","Keyworded","argument","list","with","keys","such","as",":","obj",":","`","``","node_feature","''","`",",",":","obj",":","`","``","node_label","''","`","and","corresponding","attributes","."]
docstr: List of G.edges to torch tensor for key, which dimension
  [num_edges x key_dim].
  
  Only the selected edges' attributes are extracted.
docstr_tok: ["List","of","G.edges","to","torch","tensor","for","key",",","which","dimension","[","num_edges","x","key_dim","]",".","Only","the","selected","edges","'","attributes","are","extracted","."]
code: def _get_edge_attributes_by_key(self, edges, key: str):
      r"""
      List of G.edges to torch tensor for key, which dimension
      [num_edges x key_dim].
  
      Only the selected edges' attributes are extracted.
      """
      if len(edges) == 0:
          raise ValueError(
              "in _get_edge_attributes_by_key, "
              "len(edges) must be larger than 0"
          )
      if not isinstance(edges[0][-1], dict) or key not in edges[0][-1]:
          return None
  
      attributes = {}
      for edge in edges:
          head_type = self.G.nodes[edge[0]]["node_type"]
          tail_type = self.G.nodes[edge[1]]["node_type"]
          edge_type = edge[-1]["edge_type"]
          message_type = (head_type, edge_type, tail_type)
          if message_type not in attributes:
              attributes[message_type] = []
          attributes[message_type].append(edge[-1][key])
  
      for message_type in attributes:
          if torch.is_tensor(attributes[message_type][0]):
              attributes[message_type] = torch.stack(
                  attributes[message_type], dim=0
              )
          elif isinstance(attributes[message_type][0], float):
              attributes[message_type] = torch.tensor(
                  attributes[message_type], dtype=torch.float
              )
          elif isinstance(attributes[message_type][0], int):
              attributes[message_type] = torch.tensor(
                  attributes[message_type], dtype=torch.long
              )
          if self.is_undirected():
              attributes[message_type] = torch.cat(
                  [attributes[message_type], attributes[message_type]],
                  dim=0,
              )
  
      return attributes
  
imports: import math
  import copy
  import random
  import torch
  import networkx
  import numpy
  from deepsnap.graph import Graph
  from typing import Dict, List, Union
  import warnings
label_desc: Use image node_id 28 for calling the HeteroGraph obj's underlying member method code with example usage: obj._get_edge_attributes_by_key(edges, key) and returns: attributes, None