-
Notifications
You must be signed in to change notification settings - Fork 1
/
07-properties-getters-setters.py
153 lines (115 loc) · 3.59 KB
/
07-properties-getters-setters.py
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#### GETTERS AND SETTERS
# they are methods (actions)
# their purpose is to get and set the value of an instance attribute
# they protect data by providing an indirect way to access and modify it
### GETTERS
# indirict way of accessing an attribute
# get_ + <attribute>s
class Dog:
def __init__(self, name):
self._name = name # protected attribute
def get_name(self): # getter, usuallly has one parameter self
return self._name
dog = Dog("Nora")
dog.get_name()
### SETTERS
# indirect way of modifying an attribute
# you can validate the new value before you assign it to the protected attribute
# set_ + <attribute>
class Dog2:
def __init__(self, name):
self._name = name # protected attribute
def get_name(self): # getter, usuallly has one parameter self
return self._name
def set_name(self, name): # setter,
if isinstance(name, str): # check if the new name is a string
self._name = name
else:
print("Please, enter a valid name")
dog1 = Dog2("Nora")
dog1.set_name(123)
dog1.set_name("Emily")
dog1.get_name()
## PROPERTIES = PYTHONIC WAY OF CREATING GETTERS AND SETTERS
# way of connecting attributes with their getters and setters
class Dog3:
def __init__(self, name):
self._name = name # protected attribute
def get_name(self): # getter, usuallly has one parameter self
return self._name
def set_name(self, name): # setter,
if isinstance(name, str): # check if the new name is a string
self._name = name
else:
print("Please, enter a valid name")
age = property(get_name, set_name) # property
# @property decorator
# avoid calling property()
# avoid namespace pollution (no get_<attr> or set_<attr>)
# decorator = a function that takes a function as argument to extend its functionality without actually modifying it
class Dog4:
def __init__(self, age):
self._age = age # protected attribute
@property
def age(self):
print("Running getter")
return self._age
@age.setter
def age(self, new_age):
print("Running setter")
if isinstance(new_age, int) and 0 < new_age < 30:
self._age = new_age
else:
print("Please enter a valid age")
@age.deleter # deleter!
def age(self):
print("Deleter")
del self._age
final_dog = Dog4(12)
final_dog.age
final_dog.age = 31
final_dog.age = 16
del final_dog.age
### Assignment
class BouncyBall:
def __init__(self, price, size, brand):
self._price = price
self._size = size
self._brand = brand
@property
def price(self):
print("Price getter")
return self._price
@property
def size(self):
print("Size getter")
return self._size
@property
def brand(self):
print("Brand getter")
return self._brand
@price.setter
def price(self, new_price):
if isinstance(new_price, int):
print("Setter")
self._price = new_price
else:
print("Price must be integer")
@size.setter
def size(self, new_size):
if isinstance(new_size, int):
print("Setter")
self._size = new_size
else:
print("Size must be integer")
@brand.setter
def brand(self, new_brand):
if isinstance(new_brand, str):
print("Setter")
self._brand = new_brand
else:
print("Brand must be character string")
bb = BouncyBall(12, 1, "Pyku")
bb.brand = "Mine"
bb.size = 12
bb.price = 2