开发者

Keeps only one entry instead of appending to the dictionary

开发者 https://www.devze.com 2023-02-23 22:12 出处:网络
I want to take person\'s name and their phone number from the end user and append to a dictionary. I started with an empty dictionary.

I want to take person's name and their phone number from the end user and append to a dictionary. I started with an empty dictionary.

After first user inputs the data, the program will say a new entry is added and display what is inside the updated dictionary. It works fine so far.

When the second user inputs the data it should do the same thing:

  1. Say a new entry is added
  2. Display everything in the dictionary meaning, first user's as well as second user's input. But it is not working as expected. It only shows the second user's input but not first user's input.

Can someone tell why this is failing to append to the existing data? I see only one entry each time (whoever is the latest).

Here is the program:

class phonebook:
    allphones = {} # Empty dictionary

    def __init__ (self, name, phone):
        self.pername = name
        self.perphone = phone

    def adddata(self):
        phonebook.allphones[self.pername] = self.perphone # append to the dictionary
        print ('A new phone book entry added - {0}:{1}'.format(self.pername, self.perphone)) # confirm the input
        print (phonebook.allphones) # display what is inside the phonebook  
name = input('Type person\'s name --> ')
phone = input('Type phone\'s name --> ')
adding = phonebook(name, phone)
adding.adddata()

Here is the updated program <-----------

class phonebook:

    def __init__ (self):
        self.allphones = {}

    def adddata(self, name, phone):
        self.allphones[name] = phone # append to the dictionary
        print ('A new phone book entry added - {0}:{1}'.format(name, phone)) # confirm the input
        print (self.allphones) # dump the complete phonebook data

name = input('Type person\'s name --> ')
phone = input('Type person\'s phone number --> ')

adding = phonebook()
adding.adddata(name, phone)

Here is the output I get (I want {'abc': '123', 'ghj': '505050'} as the answer) -

>>> ================================ RESTART ================================
>>> 
Type person's name --> abc
Type person's phone number --> 123
A new phone book entry added - abc:123
{'abc': '123'}
>>> ================================ RESTART ================================
>>> 
Type person's 开发者_如何学编程name --> ghj
Type person's phone number --> 505050
A new phone book entry added - ghj:505050
{'ghj': '505050'} 
>>> 


I think you seriously messed up what should be an attribute of the class and what should not. Think of it this way: your phonebook class has a dictionary in it, hence a dictionary should be an attribute. The name and phone of the person you're adding should be parameters to adddata, not instance vars of the class.

How about this change:

class phonebook:
    def __init__ (self):
        self.allphones = {}  # Empty dictionary

    def adddata(self, pername, perphone):
        self.allphones[pername] = perphone

# test code
book = phonebook()
book.adddata('joe', 121212)
book.adddata('bob', 129459)

print book.allphones

For me this prints:

{'bob': 129459, 'joe': 121212}

Update: regarding your question update - not sure what you're trying to attain? Persistence of the dict across invocations of the script? Note that you only ask for one name and phone and add them to the phonebook. When you run the program again, it's all new and clean once again, so of course there's no information kept from the previous invocation.

If you need persistent storage, consider using pickle, or shelve or even a database of some kind (for example the sqlite3 module provides built-in SQLite DB access)


It seems that you'd like a phonebook that persists between the invocations of your script. shelve module provides a persistent dictionary-like object. If you replace self.allphones dictionary by such object then you get a persistent phonebook:

import shelve
from contextlib import closing

try: raw_input = raw_input
except NameError:
    raw_input = input # py3k

class phonebook:

    def __init__ (self, filename):
        self.allphones = shelve.open(filename, protocol=1, writeback=True)

    def adddata(self, name, phone):
        self.allphones[name] = phone # append to the dictionary
        self.allphones.sync()
        # confirm the input
        print ('A new phone book entry added - {0}:{1}'.format(name, phone))
        # dump the complete phonebook data
        print (dict(self.allphones.items())) 

    def close(self):
        self.allphones.close()

with closing(phonebook('.phonebook')) as adding:
    name = raw_input('Type person\'s name --> ')
    phone = raw_input('Type person\'s phone number --> ')
    adding.adddata(name, phone)

If phone is always an immutable object such as string then writeback=True and .sync() calls may be omitted. You need them when you'd like to track several phone numbers per name in a list object and use the same syntax to work with the shelve as for an ordinary Python dictionary.

Example

$ python3 phonebook.py 
Type person's name --> a
Type person's phone number --> 1
A new phone book entry added - a:1
{'a': '1'}

$ python3 phonebook.py 
Type person's name --> b
Type person's phone number --> 2
A new phone book entry added - b:2
{'a': '1', 'b': '2'}

$ python phonebook.py 
Type person's name --> c
Type person's phone number --> 3
A new phone book entry added - c:3
{'a': u'1', 'c': '3', 'b': u'2'}


Are the users going to have distinct names? If not, then Eli's first answer makes sense (his second answer is also a good point, the dictionary should probably be an instance attribute, not a class attribute).

Nonetheless, your class works for me. Perhaps the difference is the way I test it. I cut and past your class, to make the following file (phonebook.py):

    class phonebook :
            allphones = {}
            def __init__ (self, name, phone):
                self.pername = name
                self.perphone = phone

            def adddata(self):
                phonebook.allphones[self.pername] = self.perphone # append to the dictionary
                print ('A new phone book entry added - {0}:{1}'.format(self.pername, self.perphone)) # confirm the input
                print (phonebook.allphones) # display what is inside the phonebook  


    AA = phonebook('Arkanaoid', '123456789')
    AA.adddata()

    BB = phonebook('Bongo', '987654321')
    BB.adddata()

If you want to be able to append multiple phone numbers to the same person, I would do something like (warning: I haven't tried this code out)

    class phonebook :
            allphones = {}
            def __init__ (self, name):
                self.pername = name

            def add_number(self, phone)
                self.perphone = phone
                phonebook.allphones.setdefault(self.pername, [])
                phonebook.allphones.append(perphone)

So now allphones is a dictionary mapping names to lists of numbers. add_number first ensures the right list exists (defaulting to [] if it did not), and then appends to it.

0

精彩评论

暂无评论...
验证码 换一张
取 消