0

I'm teaching myself python from lecture slides but I'm struggling to get this code to work, I can't see what I did wrong! Also how would I implement address so that it is in a different class? I'm not sure the best to do this. This my attempt so far

Error that appears:

self.phone = phone

IndentationError: unexpected Indent

Simple Python phonebook

class Person:

    def __init__(self, name, age, phone, address):
        # instance variables, unique to each Person
        self.name = name
        self.age = age
        self.phone = phone
        self.address = address

    def __str__(self):
        # instance variables, unique to each Person

        return "Name: " + self.name + "\n" + "Age: " + self.age + "\n" + "Phone: " + self.phone + "\n" + "Address: " + self.address
persons = []

def createPerson():
    print("\nNew person")
    name = input('  | Name : ')
    age  = input('  | Age  : ')
    phone = input('  | Phone  : ')
    adress = input('  | Address  : ')
    print("Creating person...\n")
    person = Person(name, age, phone, address)
    persons.append(person)

def searchPerson():
    print("\nSearch person")
    key = input('  | Keyword : ')
    print("Searching...\n")
    # Find names that match given keyword
    match = [p for p in persons if p.name.startswith(key)]
    print(str(len(match)) + ' user(s) found :\n')
    for p in match:
        print(p)

if __name__ == '__main__':
    choices = { "1" : createPerson , "2" : searchPerson }
    x = "0"
    while x != "3":
        print(' (1) Create new person')
        print(' (2) Search for a person')    
        print(' (3) Quit')
        x = input('Select an option -> ')
        if x == "1" or x == "2": choices[x]()
3
  • 3
    You will need to post the error message if you want people to help you. Or if no error, explain what you want the code to do, and what result you get instead. Commented Jan 15, 2016 at 15:14
  • 1
    You're mixing tabs and spaces in your indentation, which confuses Python. Use one or the other exclusively. Preferably spaces. (I'm posting this as a comment and not an answer because I don't understand the "implement address so that it is in a different class" part of your question) Commented Jan 15, 2016 at 15:16
  • There's at least one typo: you're assigning to a variable called adress with one 'd' but then expecting to access it as address with two. Your title says you're getting an IndentError. Indentation looks ok in your StackOverflow rendering of the code, but If that's the error, verify that the indentation is consistent throughout and you're not mixing spaces and tabs. Commented Jan 15, 2016 at 15:46

2 Answers 2

4

Well, firstly, there are some typos that are preventing your code from fully working. This line, for instance: adress = input(' | Address : ') should be written with address instead (notice the double D).

To add Address as a new class, just do it as you did with Person. You can have as many classes as you want in the same file:

class Address:
    def __init__(self, address='No address defined'):
        # You could create separate fields for each part of the address, 
        # for better results in a bigger system
        self.address = address

    def __str__(self):
        return str(self.address)

You're gonna need to change the way the Person object is built as well:

class Person:
    def __init__(self, name, age, phone, address):
        # instance variables, unique to each Person
        self.name = name
        self.age = age
        self.phone = phone
        self.address = Address(address)

    def __str__(self):
        # instance variables, unique to each Person
        return "Name: {}\nAge: {}\nPhone: {}\nAddress: {}".format(self.name, self.age, self.phone, self.address)

def createPerson():
    print("\nNew person")
    name = input('  | Name : ')
    age  = input('  | Age  : ')
    phone = input('  | Phone  : ')
    address = input('  | Address  : ')
    print("Creating person...\n")
    person = Person(name, age, phone, address)
    persons.append(person)

Notice that on when overriding the __str__ method of Person, you should use format instead of concatenating strings and values with the + operator. There's an increase of performance there if you are dealing with multiple values and you also don't need to worry about problems with joining numbers with strings, for instance.

I'd also suggest that you'd use a different method for searching users. Instead of checking if a user's name startswith a key, I believe checking if the user's name contains the key is a better option, since it searches the whole string, not just the beggining:

match = [p for p in persons if key in p.name]

And finally, I've made a few changes to your entry point, to make it more intuitive to the user and prevent unwanted inputs:

def exit():
    print("Shutting down.")

if __name__ == '__main__':
    choices = { "1" : createPerson , "2" : searchPerson, "3": exit  }
    x = '1'
    while x != "3":        
        print(' (1) Create new person')
        print(' (2) Search for a person')    
        print(' (3) Quit')        
        x = input('Select an option -> ')

        if x not in ['1', '2', '3']:
            print('Please choose one of the available options.')
            continue

        choices[x]()

Of course, most of these changes are suggestions, and you can accept them or not. There are also a few other modifications that I'm sure could be done to turn the code into something more "pythonic", but those might be addressed somewhere else, by someone else, if needed. The only real answer is the one regarding turning Address into a separate class. Hope it helps :)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. This was a very in-depth answer which is perfect for someone like me just starting out with Python, much appreciated!
I'm glad it helped, it hasnt been a long time since I started working with python myself, and the community has always been great, so it's always nice to be able to give back :)
0

Change your input scan to raw_input

x = raw_input('Select an option -> ')` 

Worked for me.

raw_input gives a string which you are expecting.

Also make sure you have no tabs for indentation. Replace all tabs with 4 spaces.

3 Comments

If OP is using 3.X, and he probably is because he's treating print like a function, then raw_input is not a built-in function.
Right. But if it works, then he will never come out of the WHILE loop.
Yeah it was the fact that I used tab instead of spaces. Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.