关于类:Python类:如何处理“future” 实例

Python classes: how to handle “future” instances

我正在自学Python(2.7,没有以前的编码经验),我刚刚开始处理类和OOP概念。作为练习,我试图编写一个非常简单的通讯簿。我认为我已经设法理解了类和实例的基本知识,但是我发现很难理解的是如何在这一点上进一步开发抽象的层次。

尝试更好地解释,假设我有这个,这通常是许多教程用来介绍类的基本示例:

1
2
3
4
5
6
7
8
9
10
class Contact(object):    

    def __init__(self, name, surname, phone):

        self.name = name
        self.surname = surname
        self.phone = phone

contact1 = Contact('Mark', 'Doe', '123456789')
contact2 = Contact('Sally', 'Preston', '456789123')

到目前为止,我还可以使用contact1.attribute或其他方法做许多其他有趣的事情。没问题。

我无法理解的是:

问题1:

我不知道我会有多少联系人。如果我不知道我将拥有多少个联系人,如何创建一个方法,比如create_contact(),使我创建一个新的联系人并将其存储在列表/dict中?我怎么称呼它?我不知道如何创建它,这样我就可以在不硬编码其名称的情况下创建一个新实例,比如"contact1"等。如何使"contact1"和"contact2"的行成为动态的东西?

我试图用一个列表作为类变量来解决这个问题。类似(假设"联系人列表"已经作为类变量存在):

1
Contact.contact_list.append(Contact('Mark', 'Doe','123456789')) # obviously I'd use raw_input instead of 'Mark' etc, but I avoided it here for readability

但是我最终得到了一个无名物体的清单,我的大脑很难处理它。我可以用列表索引访问它们,但我不确定我在这里的位置是否正确…任何帮助都将不胜感激。

问题2:(有点关联,以便更好地理解问题)

如果在python cli中我放置了类似的内容(假设定义类的前一个块已经运行了):

1
>>> Contact('Bob', 'Stevens', '32165497')

我的理解是contact()的一个实例确实是用这些属性创建的…但它没有名字。如何访问它?(我怎么知道它的存在呢?是否有方法列出与某个类相关的所有现有实例?)

我希望我说得有道理。事先谢谢你的帮助。


将"无名"实例存储在集合中并没有什么错,但我同意,一开始很难让您全神贯注。;)您不需要知道要创建多少联系人,因为python集合类型都是动态的,所以您不需要事先指定大小,它们将增长以适应您提供的数据。

这是一个使用联系人类在列表字典中创建简单电话簿的演示。我们将每个联系人都保存在名字和姓氏下,这样我们就可以按任一名称查找联系人。字典的值是列表,因此我们可以处理多个同名的人。

我在Contact中添加了一个__repr__方法,以便于显示Contact实例的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from collections import defaultdict

class Contact(object):
    def __init__(self, name, surname, phone):
        self.name = name
        self.surname = surname
        self.phone = phone

    def __repr__(self):
        return '{name} {surname}: {phone}'.format(**self.__dict__)

phonebook = defaultdict(list)

data = [
    ('Mark', 'Doe', '123456789'),
    ('Sally', 'Preston', '456789123'),
    ('John', 'Doe', '789123456'),
]

for name, surname, phone in data:
    contact = Contact(name, surname, phone)
    phonebook[name].append(contact)
    phonebook[surname].append(contact)

for key, val in phonebook.items():
    print(key, val)

输出

1
2
3
4
5
Mark [Mark Doe: 123456789]
Doe [Mark Doe: 123456789, John Doe: 789123456]
Sally [Sally Preston: 456789123]
Preston [Sally Preston: 456789123]
John [John Doe: 789123456]

另一种选择是使phonebook成为Contact的类属性。

当然,要使这个程序真正有用,我们需要能够将电话簿保存到磁盘上,并能够将其重新加载。有多种方法可以做到这一点,例如将数据保存到csv或json文件,或保存到pickle文件。但这些是另一个问题的主题。;)


Q1:您可以创建另一个将用作数据库的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Contact(object):    
    def __init__(self, name, surname, phone):
        self.name = name
        self.surname = surname
        self.phone = phone

class ContactDatabase:
    def __init__(self, *args):
        self.inner_list = list(args)

    def add_contact(self, new_contact):
        self.inner_list.append(new_contact)


# Initial contacts
contact1 = Contact('Mark', 'Doe', '123456789')
contact2 = Contact('Sally', 'Preston', '456789123')

# Creating a database
my_database = ContactDatabase(contact1, contact2)

# Adding new contacts later
my_database.add_contact(Contact('Jim', 'Miller', '111223123'))