Chapter 3: Encapsulation

Property

face Josiah Wang

What if you also want to be able to update the .name property? (In a controlled manner, of course!)

lovely_person.name = "George"

All you need to do is to convert the setter method set_name() into a name property. Again, you rename set_name() to name() (Line 10) and annotate the method with a @name.setter decorator (Line 9), where @name is the name of your property. Also notice that I’ve changed the constructor back to how it was before (Line 3)

 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
27
28
29
30
31
32
class VainPerson:
    def __init__(self, name):
        self.name = name

    @property
    def name(self):
        return f"Your Most Honourable Excellency {self.__name}"

    @name.setter
    def name(self, new_name):
        if self.likes_name(new_name):
            self.__name = new_name.upper()
        else:
            if self.__name is None:
                # Just so we have a default name
                self.__name = "JOSIAH"
            else:
                print("I doth not liketh yond nameth. Off with thy headeth!")

    def likes_name(self, name):
        if name.upper() in ["EDWARD", "VICTORIA", "WILLIAM", "GEORGE",
                            "ELIZABETH", "JOSIAH"]:
            return True
        else:
            return False

lovely_person = VainPerson("Edward")
print(lovely_person.name) # Your Most Honourable Excellency EDWARD
lovely_person.name = "George"
print(lovely_person.name) # Your Most Honourable Excellency GEORGE
lovely_person.name = "Gollum" # I doth not liketh yond nameth. Off with thy headeth!
print(lovely_person.name) # Your Most Honourable Excellency GEORGE

Now, users of your VainPerson class can both read and write to the name property (in a controlled manner), and you also made your code more readable in the process!