Python; AttributeError: typeObject 'Object' has no attribute 'name', but I declared 'name' attribute

Python; AttributeError: typeObject 'Object' has no attribute 'name', but I declared 'name' attribute

我(重新)搜索了很多关于这个问题的信息,但我没有找到合适的 answer/solution,尽管很多主题都是关于类似问题的。

我在制作 roguelike 游戏(使用 libtcodpy 库)时遇到了问题。

我有 class 个对象,classes 控制对手和打开门的函数。

class 对象:

class Object:
    #obiekty
    def __init__(self, x, y, char, name, color, blocks=False, always_visible=False, remember=None, fighter=None, ai=None, item=None, equipment=None):
        self.x = x
        self.y = y
        self.char = char
        self.name = name
        self.color = color
        self.blocks = blocks
        self.always_visible = always_visible

        self.remember = remember

        if self.remember:
            self.remember.owner = self

        self.fighter = fighter
        if self.fighter: 
            self.fighter.owner = self

        self.ai = ai
        if self.ai:
            self.ai.owner = self

        self.item = item
        if self.item:
            self.item.owner = self

        self.equipment = equipment
        if self.equipment:
            self.equipment.owner = self

        self.item = Item()
            self.item.owner = self

    def move(self, dx, dy):
        #move if not blocked
        if not is_blocked(self.x + dx, self.y + dy):
            self.x += dx
            self.y += dy    

    def move_shop(self, dx, dy):
        #move in shops
        if not is_blocked(self.x + dx, self.y + dy) and is_object(self.x + dx, self.y + dy):
            self.x += dx
            self.y += dy

    def move_towards(self, target_x, target_y):
    #move to player
        dx = target_x - self.x
        dy = target_y - self.y
        ddx = 0
        ddy = 0
        if dx > 0:
            ddx = 1
        elif dx < 0:
            ddx = -1
        if dy > 0:
            ddy = 1
        elif dy < 0:
            ddy = -1
        if not is_blocked(self.x + ddx, self.y + ddy):
            self.move(ddx, ddy)
        elif is_blocked(self.x + ddx, self.y + ddy):
            if not is_door(self.x + ddx, self.y + ddy):
                if ddx != 0:
                    if not is_blocked(self.x + ddx, self.y):
                        self.move(ddx, 0)
                        return
                if ddy != 0:
                    if not is_blocked(self.x, self.y + ddy):
                        self.move(0, ddy)
                        return
            elif is_door(self.x + ddx, self.y + ddy):
                if ddx != 0:
                    use_door(object)
                    return
                elif ddy != 0:
                    use_door(object)
                    return

def distance_to(self, other):
    #return distance to object
    dx = other.x - self.x
    dy = other.y - self.y
    return math.sqrt(dx ** 2 + dy ** 2)

def distance(self, x, y):
    #return distance to coords
    return math.sqrt((x - self.x) ** 2 + (y - self.y) ** 2)

def send_to_back(self):
    #drawning objects
    global objects
    objects.remove(self)
    objects.insert(0, self)

def draw(self):
    if (libtcod.map_is_in_fov(fov_map, self.x, self.y) or
            (self.always_visible and map[self.x][self.y].explored)):
        libtcod.console_set_default_foreground(con, self.color)
        libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)

def clear(self):
    #erase
    if libtcod.map_is_in_fov(fov_map, self.x, self.y):
        libtcod.console_put_char_ex(con, self.x, self.y, '.', libtcod.darker_yellow, libtcod.black)

简单 'ai' class 独特 npc:

class ImpNPC1_2:
    global friendly_villages, hostile_villages, hostile_npc

    memory_x = None
    memory_y = None

    def take_turn(self):
        #monsters turn
        monster = self.owner
            if '2npc_1c' not in hostile_npc:
                if '1st_city' in friendly_villages:
                    if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
                        self.owner.move_shop(libtcod.random_get_int(0, -1, 1), libtcod.random_get_int(0, -1, 1))
                if '1st_city' in hostile_villages:
                    if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
                        self.memory_x = player.x
                        self.memory_y = player.y
                        if monster.distance_to(player) >= 2:
                            monster.move_towards(player.x, player.y)

                        elif player.fighter.hp > 0:
                            monster.fighter.attack(player)
                    elif self.memory_x != None and self.memory_y != None: #simple fake-memory
                        monster.move_towards(self.memory_x, self.memory_y)
                        if monster.x == self.memory_x and monster.y == self.memory_y or libtcod.random_get_int(0, 0, 100) > AI_INTEREST:
                            self.memory_x = None
                            self.memory_y = None
                    else:
                        while True:
                            x = libtcod.random_get_int(0, monster.x - 20, monster.x + 20)
                            y = libtcod.random_get_int(0, monster.y - 20, monster.y + 20)
                            if can_walk_between(monster.x, monster.y, x, y): break
                        self.memory_x = x
                        self.memory_y = y
            if '2npc_1c' in hostile_npc:
                if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
                    self.memory_x = player.x
                    self.memory_y = player.y
                    if monster.distance_to(player) >= 2:
                        monster.move_towards(player.x, player.y)
                    elif player.fighter.hp > 0:
                        monster.fighter.attack(player)
                elif self.memory_x != None and self.memory_y != None:
                    monster.move_towards(self.memory_x, self.memory_y)
                    if monster.x == self.memory_x and monster.y == self.memory_y or libtcod.random_get_int(0, 0, 100) > AI_INTEREST:
                        self.memory_x = None
                        self.memory_y = None
                else:
                    while True:
                        x = libtcod.random_get_int(0, monster.x - 20, monster.x + 20)
                        y = libtcod.random_get_int(0, monster.y - 20, monster.y + 20)
                        if can_walk_between(monster.x, monster.y, x, y): break
                    self.memory_x = x
                    self.memory_y = y

(是的,我知道这是重复的,但我将在 hostile_village 中指定 npc 的行为)。

函数use_door:

#DRZWI
def use_door(object):
    if 'locked' in object.name:
        message('The door is locked.', libtcod.white)
        return

    if 'closed' in object.name:
        map[object.x][object.y].blocked = False
        map[object.x][object.y].block_sight = False
        map[object.x][object.y].it_is_door = False
        object.blocks = False
        object.char = '/'
        object.name = 'open door'
        fov_recompute = True
    for obj in objects:
        if 'closed' in obj.name and obj.x == object.x + 1 and obj.y == object.y:
            return
        if 'closed' in obj.name and obj.x == object.x - 1 and obj.y == object.y:
            return
        if 'closed' in obj.name and obj.x == object.x and obj.y == object.y + 1:
            return
        if 'closed' in obj.name and obj.x == object.x and obj.y == object.y - 1:
            return
    initialize_fov()
    return

    if 'open' in object.name:
        map[object.x][object.y].blocked = True
        map[object.x][object.y].block_sight = True
        map[object.x][object.y].it_is_door = True
        object.blocks = True
        object.char = '+'
        object.name = 'closed door'
        fov_recompute = True
        for obj in objects:
            if 'open' in obj.name and obj.x == object.x + 1 and obj.y == object.y:
                return
            if 'open' in obj.name and obj.x == object.x - 1 and obj.y == object.y:
                return
            if 'open' in obj.name and obj.x == object.x and obj.y == object.y + 1:
                return
            if 'open' in obj.name and obj.x == object.x and obj.y == object.y - 1:
                return
        initialize_fov()
        return

其他代码片段(我认为这可能对定位问题有用):

def is_blocked(x, y):
    #check blocktiles
    if map[x][y].blocked:
        return True

    for object in objects:
        if object.blocks and object.x == x and object.y == y:
            return True

    return False

def is_object(x, y):
    #check objects
    if map[x][y].it_is_object:
        return True

    for object in objects:
        if object.blocks and object.x == x and object.y == y:
            return True

    return False

def is_door(x, y):
    #check doors
    if map[x][y].it_is_door:
        return True

    for object in objects:
        if object.blocks and object.x == x and object.y == y:
            return True

    return False

###ANOTHER_PIECE_OF_CODE

def make_1st_city():
    global map
    global objects
    global village
    global upstairs
    global downstairs
    objects = [player]
    player.x = 3
    player.y = 20
    map = [ [ Tile(True) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ]
    smap = ['################################################################################',
            '#GGHHGGGHHGGGGHGGHGHGGGHGGHGGHHGGHGHGGHHGGHGGHGHGGGHGHHHGGHGGGHHGGGHHGGHGHGHGHG#',
            '#G1111111111111111111111111111111111111111111111111111111111111111111111111111G#',
            '#H1676767676767676767676111111111111111111111111111111122222222222221111111111G#',
            '#G16767676767676767676761111111111111111111111111111111KJJJJJJJJJJJ21111111111H#',
            '#G167676767676767676767611222222K2222222K222221111111113JJJJJJJJJJJ21111111111G#',
            '#H1676767676767676767676112JJJJJJJJJJJJJJJJJJ2111111111KJJJJJJJJJJJ21111111111H#',
            '#G1676767676767676767676112JJJJJJJJJJJJJJJJJJ211111111122222222222221111111111G#',
            '#H167676767676767676767611KJJJJJJJJJJJJJJJJJJK11111111111111111111111111111111G#',
            '#H1676767676767676767676112JJJJJJJJJJJJJJJJJJ211111111111111111111111111111111G#',
            '#G16767676767676767676761122K2222K232K22222K2211111111111111111111111111111111H#',
            '#G1111111111111111111111111111111111111111111111111111111111111111111111111111H#',
            '#G1111111111111111111111111111111111111111111111111111111111111111111111111111G#',
            '#H1111111111111111111111111111111111111111111111111111222222222222222211111111H#',
            '#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#G11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#G11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#G11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#G111111111112222K222K232K222K2222111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#G111111111112JJJJJJJJJJJJJJJJJJJ2111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#H11111111111KJJJJJJJJJJJJJJJJJJJK111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#H111111111112JJJJJJJJJJJJJJJJJJJ2111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#H111111111112JJJJJJJJJJJJJJJJJJJ2111118181111111111113JJJJJJJJJJJJJJ211111111G#',
            '#G111111111112JJJJJJJJJJJJJJJJJJJ2111111911111111111112JJJJJJJJJJJJJJ211111111G#',
            '#G11111111111KJJJJJJJJJJJJJJJJJJJK111118181111111111112JJJJJJJJJJJJJJ211111111H#',
            '#H111111111112JJJJJJJJJJJJJJJJJJJ2111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#H11111111111222222222222222222222111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#G11111111111232232232232232232211111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#G111111111112JJ2JJ2JJ2JJ2JJ2JJ211111111111111111111112JJJJJJJJJJJJJJ211111111G#',
            '#H111111111112JJ2JJ2JJ2JJ2JJ2JJ211111111111111111111112JJJJJJJJJJJJJJ211111111H#',
            '#G6776711111122222222222222222221111111111111111111111222222222222222211111111G#',
            '#G6677666711111111111116676676766667111111111111111111116777676711111111111111H#',
            '#54454667676777766766767745455444667667666761111166776677456676767611111111111H#',
            '#41145544776745454544677451111144446667674466677677676745444545676676111111111H#',
            '#41111114554541111114454511111111145664455444547776764541114444454676776711111G#',
            '#51111111111111111111111111111111114444111111445544454411111144544567676767677H#',
            '#41111111111111111111111111111111111111111111111111111111111111444445545666766H#',
            '#41111111111111111111111111111111111111111111111111111111111111111555554545455G#',
            '#GGGHHGHHHHHGGGGHGGHGHGGGHGHGGHGHGGHGHGGHGHGGGHGGGGHGHHGGGHGHGGHGHGHHGGHGHGGHGG#',
            '################################################################################',]
    MAP_HEIGHT1 = len(smap)
    MAP_WIDTH1 = len(smap[0])
    map = [ [ Tile(True) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ]
    for y in range(MAP_HEIGHT1):
        for x in range(MAP_WIDTH1):
            if smap[y][x] != '#':
                map[x][y] = Tile(False)
            if smap[y][x] == '#':
                map[x][y] = Tile(True)
            if smap[y][x] == '1':
                map[x][y] = Tile(False)
            if smap[y][x] == '2':
                wall = Object(x, y, '#', 'wall', libtcod.darker_gray, always_visible=True)
                objects.append(wall)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == '3':
                door = Object(x, y, '+', 'closed door', libtcod.darkest_flame, always_visible=True)
                objects.append(door)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = True
            if smap[y][x] == '4':
                mountain1 = Object(x, y, '^', 'mountain', libtcod.dark_gray, always_visible=True)
                objects.append(mountain1)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == '5':
                mountain2 = Object(x, y, '^', 'mountain', libtcod.white, always_visible=True)
                objects.append(mountain2)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == '6':
                long_grass1 = Object(x, y, ';', 'long grass', libtcod.desaturated_yellow, always_visible=True)
                objects.append(long_grass1)
                map[x][y].blocked = False
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == '7':
                long_grass2 = Object(x, y, ';', 'long grass', libtcod.desaturated_chartreuse, always_visible=True)
                objects.append(long_grass2)
                map[x][y].blocked = False
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == '8':
                tree = Object(x, y, 'T', 'tree', libtcod.dark_green, always_visible=True)
                objects.append(tree)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == '9':
                tree2 = Object(x, y, '"', 'tree', libtcod.darker_orange, always_visible=True)
                objects.append(tree2)
                map[x][y].blocked = True
                map[x][y].block_sight = False
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == 'G':
                grass4 = Object(x, y, ',', 'grass', libtcod.darker_orange, always_visible=True)
                objects.append(grass4)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == 'H':
                grass6 = Object(x, y, ';', 'long grass', libtcod.darkest_orange, always_visible=True)
                objects.append(grass6)
                map[x][y].blocked = True
                map[x][y].block_sight = True
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False
            if smap[y][x] == 'J':
                floor = Object(x, y, '.', 'floor', libtcod.darkest_orange, always_visible=True)
                objects.append(floor)
                map[x][y].blocked = False
                map[x][y].block_sight = False
                map[x][y].it_is_object = True
                map[x][y].it_is_door = False
            if smap[y][x] == 'K':
                window = Object(x, y, '.', 'window', libtcod.lightest_sky, always_visible=True)
                objects.append(window)
                map[x][y].blocked = True
                map[x][y].block_sight = False
                map[x][y].it_is_object = False
                map[x][y].it_is_door = False

    npc = Object(32, 7, 't', '1st npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_1())
    objects.append(npc)
    npc = Object(60, 4, 't', '2nd npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_2())
    objects.append(npc)
    npc = Object(27, 22, 't', '3rd npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_1())
    objects.append(npc)
    npc = Object(60, 22, 't', '4th npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_1())
    objects.append(npc)

    upstairs = Object(3, 20, '<', 'stairs', libtcod.white, always_visible=True)
    objects.append(upstairs)
    upstairs.send_to_back()

    downstairs = Object(30, 41, '^', 'mountain', libtcod.white, always_visible=False)
    objects.append(downstairs)

有什么问题吗?播放器和计算机使用相同的开门机制。玩家可以毫无问题、错误和崩溃地打开门。当计算机尝试打开门时,应用程序崩溃。

回溯:

Traceback (most recent call last):
  File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 13441, in <module>
    main_menu()
  File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 13422, in main_menu
    play_game()
  File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 13404, in play_game
    object.ai.take_turn()
  File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 633, in take_turn
    monster.move_towards(player.x, player.y)
  File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 252, in move_towards
    use_door(object)
  File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 11272, in use_door
    if 'locked' in object.name:
AttributeError: type object 'object' has no attribute 'name'
24 bits font.
key color : 0 0 0
24bits greyscale font. converting to 32bits

我知道调用 class 'Object' 是不幸的,但如果我将其替换为 Thing,trackback 是相同的:只有 "AttributeError: type object 'object' has no attribute 'name' " 更改为 "AttributeError: class Thing has no attribute 'name' "

在您的 move_towards 函数中:

        elif is_door(self.x + ddx, self.y + ddy):
            if ddx != 0:
                use_door(object)
                return
            elif ddy != 0:
                use_door(object)
                return

您似乎希望 use_door 的参数成为坐标 self.x + ddx, self.y + ddy 处的对象,但这不是您在此处传递的内容。您只是传递了内置的 object class,这与您定义的 Object class 无关。我无法从您的代码片段中判断这是否可行,但请尝试从 map.

中获取对象
        elif is_door(self.x + ddx, self.y + ddy):
            if ddx != 0:
                use_door(map[self.x + ddx][self.y + ddy])
                return
            elif ddy != 0:
                use_door(map[self.x + ddx][self.y + ddy])
                return