带有运算符重载的自定义类型的Python检查错误

时间:2016-09-25 06:19:36

标签: python python-3.x operator-overloading

问题:我似乎无法通过类型检查解决一些Python代码检查错误。

背景:在我的特定应用程序中,有一个" Galaxy"网格,每个扇区是另一个较小位置的网格。换句话说,您可以将地图视为整个全局网格(例如100x100),或者作为10x10网格的" Sectors"组成银河系,每个扇区本身就是一个10x10网格点。

我正在创建一个Coordinate类来管理这些行/列对,我在这些对象上定义了 add mul 。 Add通过对x / y分量执行向量加法来组合两个坐标,而Mul只是按整数或浮点值对两个维度进行缩放。

我还有一些函数可以将一对10x10(Galaxy + Sector)坐标组成全局(100x100)坐标空间,反之亦然。

数学运算正常,但代码检查员不满意并抱怨类型检查,我无法弄清楚发生了什么。

值得注意的是,我无法使用" Coordinate"来标注Coordinate的成员函数。返回类型,因为它声称是" unknown",大概是因为编译器仍在处理类的定义。

建议表示赞赏,谢谢!

以下是我遇到的错误:

Python Type checker
Coordinate.py
Expected type 'Number', got 'Coordinate' instead
Type 'int' doesn't have expected attributes 'row', 'col'
Unresolved references
Coordinate.py
Unresolved attribute reference 'row' for class 'int'
Unresolved attribute reference 'col' for class 'int'

以下是代码:

import math


class Constants:
    GALAXY_SIZE = 10
    SECTOR_SIZE = 10


class Coordinate:
    def __init__(self, r=0, c=0):
        """ stores an integer row and column coordinate for a rectangular coordinate system.
            """
        self.row = r
        self.col = c

    def __repr__(self):
        return 'Coord({self.row}, {self.col})'.format(self=self)

    def __str__(self):
        return '({self.row}, {self.col})'.format(self=self)

    def __hash__(self):
        return hash(str(self))

    def __eq__(self, other):
        return self.row == other.row and self.col == other.col

    def __mul__(self, other):

        if isinstance(other, (int, float)):
            return Coordinate(self.row * other, self.col * other)
        else:
            return NotImplemented

    def __add__(self, other):

        if isinstance(other, Coordinate):
            return Coordinate(self.row + other.row, self.col + other.col)
        elif isinstance(other, (int, float)):
            return Coordinate(self.row + other, self.col + other)
        else:
            return NotImplemented

    def restrict_to_bounds(self, low, high):
        self.row = apply_bound(self.row, low.row, high.row)
        self.col = apply_bound(self.col, low.col, high.col)
        return self


# helper math functions
def apply_bound(val, low, high):
    if val < low:
        val = low
    elif val > high:
        val = high
    return val


def convert_direction(direction):
    # convert map direction (0 degrees = up) to trigonometric angle (0 = +x direction, 90 = up)
    # assumes direction is in [0-360]
    # returns radians
    assert 0 <= direction <= 360, "invalid direction conversion"

    theta = 90 - direction
    if theta < 0:
        theta += 360

    return math.radians(theta)


def abs_ceil(x):
    # truncate value towards 
    if x < 0:
        x = math.floor(x)
    else:
        x = math.ceil(x)
    return x


def calc_move_offsets(direction, sectors):
    # while the user perceives the galaxy as Constants.GALAXY_SIZE sectors of Constants.SECTOR_SIZE, logically the
    # galaxy is a flat grid of Constants.GALAXY_SIZE * Constants.SECTOR_SIZE coordinates across, so we calculate moves
    # in global coordinates.
    # one sector is equivalent to exactly one Constants.SECTOR_SIZE of global coordinates.
    theta = convert_direction(direction)
    x = math.trunc(sectors * Constants.SECTOR_SIZE * math.cos(theta))
    y = -math.trunc(sectors * Constants.SECTOR_SIZE * math.sin(theta))

    return Coordinate(y, x)


def galsec_to_global(gal: Coordinate, sec: Coordinate) -> Coordinate:
    # convert galactic/sector coord pair to global coordinate

错误预期类型&#39;数字&#39;,得到&#39;坐标&#39;代替。这突出了&#34; sec&#34;在以下一行:

    return (gal * Constants.SECTOR_SIZE) + sec  


def global_to_galsec(global_coord) -> (Coordinate, Coordinate):
    # convert galactic/sector coord pair to global coordinate
    gal = Coordinate(int(global_coord.row / Constants.SECTOR_SIZE), int(global_coord.col / Constants.SECTOR_SIZE))
    sec = global_coord + (gal * -Constants.SECTOR_SIZE)
    return gal, sec


def calc_global_move(delta, gal_coord: Coordinate, sector_coord: Coordinate) -> Coordinate:
    gl = galsec_to_global(gal_coord, sector_coord)

    # debug_print('global1:', gl)
    # debug_print('delta:', delta)

    gl += delta
    gl.restrict_to_bounds(Coordinate(0, 0), Coordinate(Constants.GALAXY_SIZE * Constants.SECTOR_SIZE - 1,
                                                       Constants.GALAXY_SIZE * Constants.SECTOR_SIZE - 1))
    # debug_print('global2:', gl)
    # debug_print('global2gs:',  global_to_galsec(gl))

    return global_to_galsec(gl)


# noinspection PyAugmentAssignment
def tests():
    print('running tests')
    # check some basic coordinate conversions
    gal = Coordinate(1, 2)
    sec = Coordinate(3, 4)
    gl = galsec_to_global(gal, sec)
    assert gl.row == gal.row * Constants.SECTOR_SIZE + sec.row
    assert gl.col == gal.col * Constants.SECTOR_SIZE + sec.col
    g2, s2 = global_to_galsec(gl)
    assert gal == g2

错误:输入&#39; int&#39;没有预期的属性&#39; row&#39;,&#39; col&#39;。 Python似乎表明s2是一个int,但是它是从global_to_galsec返回的,它被注释为返回(Coordinate,Coordinate)。请注意,前一行的类似断言没有错误。

    assert sec == s2

    gal = gal * 3

错误:未解析的属性引用&#39; row&#39;为课堂&#39; int&#39; 错误:未解析的属性引用&#39; col&#39;对于课程&#39; int&#39;

    assert gal.row == 3 and gal.col == 6
    sec += Coordinate(-1, -3)
    assert sec.row == 2 and sec.col == 1


if __name__ == '__main__':
    tests()

0 个答案:

没有答案