用Python编写通讯录程序的问题

-1 投票
2 回答
2012 浏览
提问于 2025-04-17 09:46

我正在写一个程序,用来添加和更新通讯录。以下是我的代码:

已编辑

import sys
import os

list = []

class bookEntry(dict):
    total = 0

    def __init__(self):
        bookEntry.total += 1
        self.d = {}

    def __del__(self):
        bookEntry.total -= 1
        list.remove(self)

class Person(bookEntry):
    def __init__(self, n):
        self.n = n
        print '%s has been created' % (self.n)

    def __del__(self):
        print '%s has been deleted' % (self.n)

    def addnewperson(self, n, e = '', ph = '', note = ''):
        self.d['name'] = n
        self.d['email'] = e
        self.d['phone'] = ph
        self.d['note'] = note

        list.append()

    def updateperson(self):
        key = raw_input('What else would you like to add to this person?')
        val = raw_input('Please add a value for %s' % (key))
        self.d[key] = val
def startup():
    aor = raw_input('Hello! Would you like to add an entry or retrieve one?')
    if aor == 'add':
        info = raw_input('Would you like to add a person or a company?')
        if info == 'person':
            n = raw_input('Please enter this persons name:')
            e = raw_input('Please enter this persons email address:')
            ph = raw_input('Please enter this persons phone number:')
            note = raw_input('Please add any notes if applicable:')

            X = Person(n)
            X.addnewperson(n, e, ph, note)
startup()

当我运行这段代码时,出现了以下错误:

in addnewperson
    self.d['name'] = n
AttributeError: 'Person' object has no attribute 'd'

我有两个问题:

更新的问题

1. 为什么 d 这个对象没有从 bookentry() 继承呢?

我知道这个问题和代码比较长,但我不知道接下来该怎么做。任何帮助都将非常感谢。

2 个回答

4
  1. 为什么d对象没有从bookentry()继承呢?

这是因为在Person的__init__方法里没有调用bookEntry的__init__方法:

super(Person, self).__init__()

顺便问一下,如果不使用字典(dict)的功能,为什么还要继承它呢?不如去掉它,直接继承自object类会更好(而且类名通常是大写驼峰式命名):

class BookEntry(object):
4
  1. addnewperson 方法的第一个参数应该是 'self';其实名字并不重要('self' 只是个约定),但第一个参数代表的是对象本身。在你的例子中,它把 n 解释成了 "self",而其他三个参数则被当作普通参数。

  2. ____del____ 方法除了 'self' 之外不能接受其他参数。

补充:顺便说一下,我在你的例子中发现了一些其他问题,可能你还没有注意到:

1) d 在 bookentry 中是一个类成员,而不是实例成员。它是所有 bookentry 实例共享的。要创建一个实例成员,可以使用:

class bookentry(dict):
    def __init__(self,n):
        self.d = {}
        # rest of your constructor

2) 你试图直接访问 d(就像在 Java、C++ 等语言中那样),但 Python 不支持这样做。你必须在方法中有一个 'self' 参数,并通过它来访问实例变量:

class person(bookentry):
    def foo(self,bar):
       self.d[bar] = ...

person().foo(bar)

更新:关于最后一个问题,解决方案是显式调用父类构造函数(在 Python 中必须这样做):

class Person(bookEntry):
    def __init__(self, n):
        super(Person, self).__init__()
        self.n = n
        print '%s has been created' % (self.n)

简单解释一下:对于没有多重继承背景的面向对象语言的人来说,期望父类构造函数被隐式调用是很自然的,自动选择最合适的一个,如果没有明确提到的话。然而,当一个类可以同时继承两个或多个类时,事情就会变得复杂,因此 Python 要求程序员自己做出选择:要先调用哪个父类构造函数?或者根本不调用?

构造函数(和析构函数)的行为在不同语言中可能差异很大。如果你对 Python 对象的生命周期还有其他问题,可以从 这里这里这里 开始了解。

撰写回答