代码之家  ›  专栏  ›  技术社区  ›  Diego-MX

python类和类型

  •  0
  • Diego-MX  · 技术社区  · 6 年前

    我想我误用了子类的概念。我正在做一个有网格和单元格的爱好项目。

    我所拥有的是 Cell 类及其子类 HexCell 它基本上重新定义了许多属性/方法,如下所示:

    class Cell: 
    
      def __init__(self, row_loc, col_loc):
        self.row = row_loc
        self.col = col_loc
        self.links = set()
        self.neighbors = 4*[None]
    
      def __repr__(self):
        return f'Cell @({self.row},{self.col})'
    
      def link(self, other, bidir = True):
        self.links.add(other)
        if bidir: other.links.add(self)
    

    我有一个子类是 HexGrid 它遵循了一个具有新参数的类似结构。

    class HexCell(Cell):
      def __init__(self, r_out, th_around):
      # I'm indexing Hex cells around a center cell 
      # instead of by rows and columns; Prefixed hex
      # as they follow the hexagon, and not regular polar coordinates. 
        self.hex_r     = r_out
        self.hex_th    = th_around
        self.neighbors = 6*[None]
        self.links     = set()
    
      def __repr__(self):
        return f"HexCell @[{self.hex_r}, {self.hex_th}]"
    
      def bind(self, other, to_dir):
        to_dir = to_dir % 6
        if (self.neighbors[to_dir] is None):
          self.neighbors[to_dir] = other
          other.neighbors[to_dir - 3] = self
    
        # Hexagonal grids share neighbors. 
        other_1 = other.neighbors[to_dir - 2]
        if (self.neighbors[to_dir - 1] is None) & (other_1 is not None):
          self.bind(other_1, to_dir - 1)
        other_5 = other.neighbors[to_dir - 4]
        if (self.neighbors[to_dir - 5] is None) & (other_5 is not None):
          self.bind(other_5, to_dir - 5)
    

    在这种情况下,方法 self.link(other) 共享,但其他属性从矩形网格更改为六边形,如 (row, col) (hex_r, hex_th) neighbors 作为一个4列表或6列表。因此,我希望这些属性依赖于另一个单元格类型属性并向下传递到子类。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Olivier Melançon iacob    6 年前

    正确使用子类需要遵循以下替换原则:

    如果有什么东西 x_1 类型 T_1 x_2 类型 T_2 如此 issubclass(T_2, T_1) == True ,则任何适用于 XY1 也必须申请 XY2

    换句话说,您希望子类化实现 新的 行为,而不是 改变 现有行为。

    在您的例子中,坐标系本身的变化是行为的变化,因此 HexCell 不应继承自 Cell .

    你能做的就是创建一个基类 BaseCell 它封装了 细胞 己糖细胞 从中继承。

    class BaseCell:
        def __init__(self):
            self.links = set()
            self.neighbors = []
    
        def add_neighbor(self, other):
            self.neighbors.append(other)
    
        def link(self, other, bidirectional=True):
            self.links.add(other)
            if bidirectional:
                other.link(self, bidirectional=False)
    
    
    class Cell(BaseCell):
        def __init__(self, row_loc, col_loc):
            self.row = row_loc
            self.col = col_loc
            super().__init__()
    
        def __repr__(self):
            return f'Cell @({self.row},{self.col})'
    
    
    class HexCell(Cell):
        def __init__(self, r_out, th_around):
            self.hex_r = r_out
            self.hex_th = th_around
            super().__init__()
    
        def __repr__(self):
            return f"HexCell @[{self.hex_r}, {self.hex_th}]"
    
        def bind(self, other, to_dir):
            ...
    
        2
  •  1
  •   jbet    6 年前

    实际上,cell类不是抽象的“cell”,而是二维空间中的一个正方形单元格(正好有4个邻居,具有“row”和“col”位置)。此类单元格不能由十六进制单元格子类,因为十六进制单元格只是一种不同类型的单元格:)

    正如您所注意到的,惟一常见的是link()方法和links属性。如果坚持子类化,可以创建如下内容:

    class LinkedObject():
        def __init__(self):
            self.links = set()
    
        def link(self, other, bidir = True):
            self.links.add(other)
            if bidir: other.links.add(self)
    
    class SquareCell(LinkedObject):
        # "Cell" class here
    
    class HexCell(LinkedObject):
        # HexCell here