【问题标题】:Python: Checking whether an object already exists before creating a new onePython:在创建新对象之前检查对象是否已经存在
【发布时间】:2014-08-21 14:27:59
【问题描述】:

请帮我看看我在下面缺少什么。我首先创建了我班级的三个对象并将它们添加到集合列表中。在创建任何其他对象之前,我想 检查 以确保该人不存在于列表中。如果该人已经存在,则不应再次创建该人。我希望通过if prompt_fname == person.fname and prompt_lname == person.lname: 来实现这个检查。显然,我没有正确执行它,因为程序仍然运行并创建了列表中已经存在的同一个人。它两次创造了这个人。我如何修改才能捕捉到这一点,以便不再创建列表中已经存在的人。此外,不应在循环的每次迭代中一次又一次地创建任何新人。我是编程新手,所以请不要在答案中遗漏太多细节。非常感谢。

class Person(object):

    personslist = []
    '''Creates a person object'''
    def __init__(self, firstname, lastname):
        self.lname = lastname.title()
        self.fname = firstname.title()
        Person.personslist.append(self)

    def __str__(self):
        return "{0} {1}".format(self.fname, self.lname)

    def __repr__(self):
        return "{0} {1}".format(self.fname, self.lname)


Person("Adamu", "Emeka")
Person("Femi", "Ojukwu")
Person("Wole", "Jonathan")


prompt_fname = "Adamu"
prompt_lname = "Emeka"

print(Person.personslist)

for person in Person.personslist:
    if prompt_fname == person.fname and prompt_lname == person.lname:
        pass
    else:
        Person(prompt_fname, prompt_lname)

print(Person.personslist)

产量

[Adamu Emeka, Femi Ojukwu, Wole Jonathan]
[Adamu Emeka, Femi Ojukwu, Wole Jonathan, Adamu Emeka, Adamu Emeka]

使用 Python 3.4.1

【问题讨论】:

  • 随着您添加新人,您的列表会不断增加
  • 我没看到。应该使用下面的答案中指出的标志。感谢您的回答:简洁。

标签: python for-loop python-3.x


【解决方案1】:

您的循环正在检查每个条目,如果该特定条目不相等,它会创建另一个实例。但是如果那个特定的条目 相等,它不会停止,它只是继续到下一个不相等的条目。这就是为什么你在最后得到了两个额外的条目。

您可以通过保留标志来解决此问题:

found = False
for person in Person.personslist:
    if prompt_fname == person.fname and prompt_lname == person.lname:
        found = True
        break
if not found:
    Person(prompt_fname, prompt_lname)

但是,有一种更好的方法可以做到这一点:您的方法效率非常低,因为它每次都需要进行线性扫描。相反,保留一个以全名为键的对象字典:

class Person(object):

    persons_dict = {}
    '''Creates a person object'''
    def __init__(self, firstname, lastname):
        self.lname = lastname.title()
        self.fname = firstname.title()
        fullname = "%s %s" % (self.fname, self.lname)
        Person.persons_dict[fullname] = self

现在您可以直接签到:

if "%s %s" % (prompt_fname, prompt_lname) not in Person.persons_dict:

【讨论】:

  • 感谢丹尼尔指出!我真的应该明白为什么这个名单不断增长。我错过了这个。
  • 请在此处查看我的实现:ideone.com/Vq5MpH。我是否正确实施了您的建议,因为它给了我:{'Adamu Emeka': Adamu Emeka, 'Femi Ojukwu': Femi Ojukwu, 'Wole Jonathan': Wole Jonathan} {'Adamu Emeka': Adamu Emeka, 'Femi Ojukwu': Femi Ojukwu, 'Wole Jonathan': Wole Jonathan}.
  • 但这不是你想要的输出吗? dict前后一致,表示你没有添加重复。
  • 我现在看到了,key:value 对是一样的。
  • 你知道我怎样才能从persons_dict中得到一个有序的字典吗?字典本质上是无序的,here 建议从元组开始。如果我从一个元组开始,我不能向它添加新的人对象,因为元组是immutable。有什么进一步的建议吗?谢谢。
【解决方案2】:

每次添加名称前检查完整列表:

name = prompt_fname + prompt_lname

if not any(person.fname + person.lname == name for person in Person.personslist):
    Person(prompt_fname, prompt_lname)

【讨论】:

    【解决方案3】:

    这段代码没有做它应该做的事情:

    for person in Person.personslist:
        if prompt_fname == person.fname and prompt_lname == person.lname:
            pass
        else:
            Person(prompt_fname, prompt_lname)
    

    使用for person in Person.personslist:,它会遍历您已经创建的三个 Person() 对象。第一个是“Adamu Emeka”,因此名称相同,“if”语句达到“pass”。但是,personslist 中的下一项名为“Femi Ojukwu”,而if 中的名称不相等,因此它到达else 子句并创建一个新对象。第三个名字也是如此。这就是为什么你有两个额外的 Adamu Emeka 副本。

    查看 Daniel Roseman 的替代解决方案的答案

    【讨论】:

    • 请注意,如果例如“Fred Jones”和“Mike Smith”已经在列表中并且用户尝试添加“Mike Jones”,则第二个代码示例会失败——应该成功但没有采用这种设计。
    • 很好,我将删除该建议以支持 Daniel Roseman 提供的建议
    【解决方案4】:

    尝试:

    if prompt_fname.title() == person.fname and prompt_lname.title() == person.lname:
    

    因为你在Person的init中使用了title()方法

    【讨论】:

    • 试过了。结果是一样的。虽然这是一个很好的收获,但由于我的输入是正确大写的,我认为这并不重要。
    【解决方案5】:

    在您的代码中,一旦您找到一个不是 Adamu Emeka 的人,您就会将另一个 Adamu Emeka 添加到列表中。这就是添加两个 Adamu Emeka 的原因。请尝试以下操作:

    alreadyExists = False;
    for person in Person.personslist:
        if prompt_fname == person.fname and prompt_lname == person.lname:
            alreadyExists = True;
            break;
    if not alreadyExists:
        Person(prompt_fname, prompt_lname)
    

    更好的方法可能是使用set,这样您就不必执行线性搜索。要使设置正常工作,您必须implement __hash__ and __eq__ methods

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 2015-03-28
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 2017-08-10
      相关资源
      最近更新 更多