繁体   English   中英

先前定义的类方法上的 Name Error 和应该存在的 Index 上的 IndexError

[英]Name Error on a class method previously defined and IndexError on an Index that should exist

所以,我在 npc.name 上得到了一个 NameError(我想它会出现在我试图重新定义的所有后续类方法链接变量中),而且,我有一个更早出现的 IndexError 。

我将更详细地解释,但首先,我的代码。

这是我的完整代码,请注意:

# import pickle
import pickle
npcs_pickle_file = 'NPCatt.pk'
npc_count = 200

class NPC:
    def __init__(self, name="", occupation="", weakness="", need="", desire="", enemy="",
                 rumor="", secret="", passion="", redeeming_quality="",damning_quality="", happy="",
                 occ_desire="", occ_complication="", pc_opinion="", accomplishment="", magical_gear="",
                 political_influence="", resource="", intel="", research=""):

        # Attributes
        self.name = name
        self.occupation = occupation
        self.weakness = weakness
        self.need = need
        self.desire = desire
        self.enemy = enemy
        self.rumor = rumor
        self.secret = secret
        self.passion = passion
        self.redeeming_quality = redeeming_quality
        self.damning_quality=damning_quality
        self.happy = happy
        self.occ_desire = occ_desire
        self.occ_complication = occ_complication
        self.pc_opinion = pc_opinion
        self.accomplishment = accomplishment
        self.magical_gear = magical_gear
        self.political_influence = political_influence
        self.resource = resource
        self.intel = intel
        self.research = research


    def __str__(self):
        npc_output = "####NPC SUMMARY####\n"
        for att, val in self.__dict__.items():
            if val:
                npc_output += (f"{att} = {val}\n")
        return npc_output

# open a pickle file
# load your data back to memory when you need it
try:
    with open(npcs_pickle_file, 'rb') as fi:
        npcs = pickle.load(fi)
except FileNotFoundError as fne:
    #file doesnt exist prob first time running so create a dict with the 170 npc id's
    npcs = {id: None for id in range(npc_count)}


#select an NPC to modify / create
npc_id = None
while not npc_id:
    try:
        npc_id = int(input(f"Enter the id number of the NPC you wish to modify: "))
    except ValueError as ve:
        print("You must provide a numerical id")

    if npc_id < 0 or npc_id >= npc_count:
        npc_id = None
        print(f"you must provide a value between 0 and {npc_count}")



if npcs[npc_id]:
    npc = npcs[npc_id]
    print(npc)
    modify = input("This NPC already exists, do you want to continue and change them? (y/n): ")
    if modify.lower() == "y":
        name = input("Enter name of NPC: ") 
        occupation = input("Enter NPC occupation: ")
        weakness= input("Enter Weakness: ")
        need= input("Enter Need: ")
        desire= input("Enter Desire: ")
        enemy= input("Enter Enemy: ")
        rumor= input("Enter Rumor: ")
        secret= input("Enter Secret: ")
        passion= input("Enter Passion: ")
        redeeming_quality=input("Enter Redeeming Quality: ")
        damning_quality=input("Enter Damning Quality: ")
        happy= input("Enter, is this NPC happy?: ")
        occ_desire= input("Enter an Occupational Desire: ")
        occ_complication= input("Enter an Occupational Complication: ")
        pc_opinion= input("Enter this NPC's disposition toward the PCs: ")
        accomplishment= input("Enter an Accomplishment: ")
        magical_gear= input("Enter Magical Gear: ")
        political_influence=input("Enter Political Influence: ")
        resource= input("Enter Resource Level: ")
        intel= input("Enter Intel Tier: ")
        research= input("Enter Research: ")

        npc.name = name
        npc.occupation = occupation
        npc.weakness = weakness
        npc.need = need
        npc.desire= desire
        npc.enemy= enemy
        npc.rumor= rumor
        npc.secret= secret
        npc.passion= passion
        npc.redeeming_quality= redeeming_quality
        npc.damning_quality= damning_quality
        npc.happy= happy
        npc.occ_desire=occ_desire
        npc.occ_complication=occ_complication
        npc.pc_opinion=pc_opinion
        npc.accomplishment=accomplishment
        npc.magical_gear=magical_gear
        npc.political_influence=political_influence
        npc.resource=resource
        npc.intel=intel
        npc.research=research


    else:    

        npcs[npc_id] = NPC(name=npc.name, occupation=npc.occupation,weakness=npc.weakness,need=npc.need,desire=npc.desire,\
                       enemy=npc.enemy,rumor=npc.rumor,secret=npc.secret,passion=npc.passion,redeeming_quality=npc.redeeming_quality,\
                       damning_quality=npc.damning_quality,happy=npc.happy,occ_desire=npc.occ_desire,\
                       occ_complication=npc.occ_complication\
                       ,pc_opinion=npc.pc_opinion,accomplishment=npc.accomplishment,\
                       magical_gear=npc.magical_gear,political_influence=npc.political_influence,resource=npc.resource,\
                       intel=npc.intel,research=npc.research)
else:
    name = input("Enter name of NPC: ") 
    occupation = input("Enter NPC occupation: ")
    weakness= input("Enter Weakness: ")
    need= input("Enter Need: ")
    desire= input("Enter Desire: ")
    enemy= input("Enter Enemy: ")
    rumor= input("Enter Rumor: ")
    secret= input("Enter Secret: ")
    passion= input("Enter Passion: ")
    redeeming_quality=input("Enter Redeeming Quality: ")
    damning_quality=input("Enter Damning Quality: ")
    happy= input("Enter, is this NPC happy?: ")
    occ_desire= input("Enter an Occupational Desire: ")
    occ_complication= input("Enter an Occupational Complication: ")
    pc_opinion= input("Enter this NPC's disposition toward the PCs: ")
    accomplishment= input("Enter an Accomplishment: ")
    magical_gear= input("Enter Magical Gear: ")
    political_influence=input("Enter Political Influence: ")
    resource= input("Enter Resource Level: ")
    intel= input("Enter Intel Tier: ")
    research= input("Enter Research: ")
    npc.name = name
    npc.occupation = occupation
    npc.weakness = weakness
    npc.need = need
    npc.desire= desire
    npc.enemy= enemy
    npc.rumor= rumor
    npc.secret= secret
    npc.passion= passion
    npc.redeeming_quality= redeeming_quality
    npc.damning_quality= damning_quality
    npc.happy= happy
    npc.occ_desire=occ_desire
    npc.occ_complication=occ_complication
    npc.pc_opinion=pc_opinion
    npc.accomplishment=accomplishment
    npc.magical_gear=magical_gear
    npc.political_influence=political_influence
    npc.resource=resource
    npc.intel=intel
    npc.research=research


with open(npcs_pickle_file, 'wb') as fi:
    # dump your data into the file
    pickle.dump(npcs, fi)

我是一个菜鸟,所以代码结构是作为我迄今为止在网站上唯一的其他问题的答案提供的。 我已经为我的目的扩展了它。

问题是,索引为 [1] 的 NPC 已完美存储,根据需要显示,并且可以修改。 但是在定义新的 NPC 时,我首先得到一个新的可索引 NPC 的 IndexError,我用一个

try: #the code for when the NPC has been previously defined
except IndexError:#the code on the last else block, for new indexes

为了检查其余的代码是否有效,并且在我将每个属性定义为的最后一个 else 块上出现 NameError

self.att=att

现在,我最好的猜测是它与局部变量和全局变量定义有关,但我不知道如何解决这两个错误。

谢谢你,如果你读完了,我很抱歉。 如果可以并且愿意,请提供帮助。

您的IndexError问题来自取消由先前版本的脚本创建的文件。 如果此文件包含有价值的数据,请暂时将其重命名,一旦您的脚本可以正常工作且足够稳定,就可以编写迁移脚本来取回旧数据。 否则,好吧,放弃它xD

wrt/NameError,它在最后一个else块中:您试图在此时确实未定义的npc变量上设置属性 - 它仅在if块中定义:

if npcs[npc_id]:
    npc = npcs[npc_id]
    # way too much code here
else:
    # repeated code here
    # and here's the issue:
    npc.something = something

你已经注意到“在不理解它们的情况下将代码混搭在一起并不总是有效”,这是一个好的开始(至少你意识到了,所以仍然有希望 xD),现在这里有另一个启示给你:“试图理解凌乱的代码很难”。 这就是为什么好的代码结构很重要。 此外,仅(或主要)依赖于它们的参数的短函数比具有大量条件和代码块的长脚本更容易理解(和测试!),这些代码块依赖于(或未)定义了大约 20 行以上的某个变量。

我通常不这样做,但在这种情况下,您可能会从结构合理的代码外观中受益。 它远非完美,可以从一些改进中受益(例如,在编辑现有的 npc 时,让用户指定他想要更改的属性,而不是要求他们重新输入所有内容)但是,那是你的工作,而不是我的 ;-)

import pickle

# coding conventions: pseudo-constants should be ALL_UPPER
NPCS_PICKLE_FILE = 'NPCatt.pk'
NPC_COUNT = 200

# coding convention: class names should be CamelCase
class Npc:
    def __init__(self, name="", occupation="", weakness="", need="", desire="", enemy="",
                 rumor="", secret="", passion="", redeeming_quality="",damning_quality="", happy="",
                 occ_desire="", occ_complication="", pc_opinion="", accomplishment="", magical_gear="",
                 political_influence="", resource="", intel="", research=""):

        # Attributes
        self.name = name
        self.occupation = occupation
        self.weakness = weakness
        self.need = need
        self.desire = desire
        self.enemy = enemy
        self.rumor = rumor
        self.secret = secret
        self.passion = passion
        self.redeeming_quality = redeeming_quality
        self.damning_quality = damning_quality
        self.happy = happy
        self.occ_desire = occ_desire
        self.occ_complication = occ_complication
        self.pc_opinion = pc_opinion
        self.accomplishment = accomplishment
        self.magical_gear = magical_gear
        self.political_influence = political_influence
        self.resource = resource
        self.intel = intel
        self.research = research

    def update(self, **values):
        for key, val in values.items():
            # make sure we're only accepted known attributes
            if not hasattr(self, key):
                raise AttributeError("Npc object has no attribute '{}'".format(key))
            setattr(self, key, val)

    def __str__(self):
        # in Python, string concatenation is better done by
        # building a list and joining it afterward
        npc_output = ["####NPC SUMMARY####"] 
        for att, val in self.__dict__.items():
            if val:
                npc_output.append(f"{att} = {val}")
        npc_output.append("") # so we have a last newline
        return "\n".join(npc_output)


class InvalidDataFile(ValueError):
    pass


def load_npcs_from_file():
    with open(NPCS_PICKLE_FILE, 'rb') as fi:
        try:
            npcs = pickle.load(fi)
        except EOFError as e:
            raise InvalidDataFile(
                "looks like {} is empy - expected a dict, got {}".format(NPCS_PICKLE_FILE, e)
            )

    # make sure we don't have incorrect data from
    # the previous version where what was pickled was a list
    if not isinstance(npcs, dict):
        raise InvalidDataFile(
            "looks like {} is obsolete or corrupted - expected a dict, got {}".format(NPCS_PICKLE_FILE, ncps)
    )

    # make sure we ALWAYS have `NPC_COUNT` npcs whatever
    # (ie: in case the pickle didn't have as many entries as expected)
    missing = NPC_COUNT - len(npcs)
    if missing > 0:
        for id in range(NPC_COUNT):
            ncps.setdefault(id, None)
    return npcs

def init_npcs():
    return {id: None for id in range(NPC_COUNT)}

def load_npcs():
    try:
        return load_npcs_from_file()

    except (FileNotFoundError, InvalidDataFile) as e:
        # so you know what's happening...
        print("got {} when trying to load npcs from file - creating a new dataset".format(e))
        return init_npcs()


def save_npcs(npcs):
    with open(NPCS_PICKLE_FILE, 'wb') as fi:
        # dump your data into the file
        pickle.dump(npcs, fi)    


def get_npc_values():
    # factor out common stuff
    # XXX you definitly want to validate user inputs
    values = {}

    values["name"] = input("Enter name of NPC: ") 
    values["occupation"] =  input("Enter NPC occupation: ")
    values["weakness"] =  input("Enter Weakness: ")
    values["need"] =  input("Enter Need: ")
    values["desire"] =  input("Enter Desire: ")
    values["enemy"] =  input("Enter Enemy: ")
    values["rumor"] =  input("Enter Rumor: ")
    values["secret"] =  input("Enter Secret: ")
    values["passion"] =  input("Enter Passion: ")
    values["redeeming_quality"] = input("Enter Redeeming Quality: ")
    values["damning_quality"] = input("Enter Damning Quality: ")
    values["happy"] =  input("Enter, is this NPC happy?: ")
    values["occ_desire"] =  input("Enter an Occupational Desire: ")
    values["occ_complication"] =  input("Enter an Occupational Complication: ")
    values["pc_opinion"] =  input("Enter this NPC's disposition toward the PCs: ")
    values["accomplishment"] =  input("Enter an Accomplishment: ")
    values["magical_gear"] =  input("Enter Magical Gear: ")
    values["political_influence"] = input("Enter Political Influence: ")
    values["resource"] =  input("Enter Resource Level: ")
    values["intel"] =  input("Enter Intel Tier: ")
    values["research"] =  input("Enter Research: ")

    return values

def update_npc(npc):
    new_values = get_npc_values()
    npc.update(**new_values)

def create_npc():
    values = get_npc_values()
    return Npc(**values)

def get_npc_id():
    #select an NPC to modify / create
    npc_id = None
    while npc_id is None:
        try:
            npc_id = int(input(f"Enter the id number of the NPC you wish to modify: "))
        except ValueError as ve:
            print("You must provide a numerical id")

        if npc_id < 0 or npc_id >= NPC_COUNT:
            npc_id = None
            print(f"you must provide a value between 0 and {NPC_COUNT}")

    return npc_id


def edit_npc(npcs):
    npc_id = get_npc_id()

    # this should be safe now... theoretically at least
    npc = npcs[npc_id]


    if npc is None:
        ok = input("This NPC doesn't exist yet, do you want to create it (y/n): ")
        if ok.strip().lower() == 'y':
            npcs[npc_id] = create_npc()
            # let the caller know something was changed
            return True
    else:
        ok = input("This NPC already exists, do you want to continue and change them? (y/n): ")
        if ok.strip().lower() == "y":
            update_npc(npc)
            # let the caller know something was changed
            return True

    # let the caller know nothing was changed
    return False

def show_npcs(npcs):
    for id, npc in npcs.items():
        print("{} : {}".format(id, npc))
    print("") # add a blank line


def get_next_action():
    while True:
        print("what do you want to do ?")
        print("S - show existing npcs")
        print("E - edit a npc")
        print("Q - quit")

        action = input(">> ").strip().upper()
        if action not in "SEQ":
            print("sorry, I don't undertand '{}'".format(action))
        return action



def main():
    npcs = load_npcs()

    while True:
        nb_valids = len([_ for _ in npcs.values() if _])
        print("we have {} valid npcs".format(nb_valids))

        action = get_next_action()

        if action == "Q":
            break

        elif action == "E":
            if edit_npc(npcs):
                print("saving data")
                save_npcs(npcs)

        elif action == "S":
            show_npcs(npcs)




if __name__ == "__main__":
    main()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM