|
1117 | 1117 | "source": [
|
1118 | 1118 | "alice1 == alice3"
|
1119 | 1119 | ]
|
| 1120 | + }, |
| 1121 | + { |
| 1122 | + "cell_type": "markdown", |
| 1123 | + "id": "748fa453-3827-4eb8-a012-f0d8d15aa183", |
| 1124 | + "metadata": {}, |
| 1125 | + "source": [ |
| 1126 | + "You can exclude attrubutes from being used to compare objects for equality by adding the argument `eq=False` to the `attr.ib` function call. Similarly, you can exclude an attribute from order comparisons by setting `order` to `False`." |
| 1127 | + ] |
| 1128 | + }, |
| 1129 | + { |
| 1130 | + "cell_type": "markdown", |
| 1131 | + "id": "6e3b0777-f567-47cb-8823-1e462d370be5", |
| 1132 | + "metadata": {}, |
| 1133 | + "source": [ |
| 1134 | + "## Hashing" |
| 1135 | + ] |
| 1136 | + }, |
| 1137 | + { |
| 1138 | + "cell_type": "markdown", |
| 1139 | + "id": "03d02551-2b9f-4d28-86a6-64c7550b847b", |
| 1140 | + "metadata": {}, |
| 1141 | + "source": [ |
| 1142 | + "Mutable objects are not hashable, which means they can not be stored in sets, or used as keys in dictionaries." |
| 1143 | + ] |
| 1144 | + }, |
| 1145 | + { |
| 1146 | + "cell_type": "code", |
| 1147 | + "execution_count": 32, |
| 1148 | + "id": "6d576453-68e9-4bae-b8b8-378565960668", |
| 1149 | + "metadata": {}, |
| 1150 | + "outputs": [ |
| 1151 | + { |
| 1152 | + "name": "stdout", |
| 1153 | + "output_type": "stream", |
| 1154 | + "text": [ |
| 1155 | + "unhashable type: 'Person'\n" |
| 1156 | + ] |
| 1157 | + } |
| 1158 | + ], |
| 1159 | + "source": [ |
| 1160 | + "try:\n", |
| 1161 | + " people = {\n", |
| 1162 | + " Person(firstname='Alice', lastname='Zosimo', age=43),\n", |
| 1163 | + " Person(firstname='Aaron', lastname='Leibovitch', age=31),\n", |
| 1164 | + " }\n", |
| 1165 | + "except Exception as error:\n", |
| 1166 | + " print(error)" |
| 1167 | + ] |
| 1168 | + }, |
| 1169 | + { |
| 1170 | + "cell_type": "markdown", |
| 1171 | + "id": "46e907e6-3278-4cec-b595-fc15a79a18ad", |
| 1172 | + "metadata": {}, |
| 1173 | + "source": [ |
| 1174 | + "One options is to make the objects unmutable." |
| 1175 | + ] |
| 1176 | + }, |
| 1177 | + { |
| 1178 | + "cell_type": "code", |
| 1179 | + "execution_count": 33, |
| 1180 | + "id": "8c34e55f-f798-417c-808a-a70cab41d9b0", |
| 1181 | + "metadata": {}, |
| 1182 | + "outputs": [], |
| 1183 | + "source": [ |
| 1184 | + "@attr.s(frozen=True)\n", |
| 1185 | + "class Person:\n", |
| 1186 | + " lastname: str = attr.ib()\n", |
| 1187 | + " firstname: str = attr.ib()\n", |
| 1188 | + " age: int = attr.ib()\n", |
| 1189 | + " \n", |
| 1190 | + " @age.validator\n", |
| 1191 | + " def age_validator(self, attribute, value):\n", |
| 1192 | + " if value < 0 or value >= 130:\n", |
| 1193 | + " raise ValueError(f'age should be between 0 and 130')" |
| 1194 | + ] |
| 1195 | + }, |
| 1196 | + { |
| 1197 | + "cell_type": "code", |
| 1198 | + "execution_count": 53, |
| 1199 | + "id": "922f49dd-c4cf-4554-9376-5e0185158f31", |
| 1200 | + "metadata": {}, |
| 1201 | + "outputs": [ |
| 1202 | + { |
| 1203 | + "data": { |
| 1204 | + "text/plain": [ |
| 1205 | + "{Person(lastname='Leibovitch', firstname='Aaron', age=31),\n", |
| 1206 | + " Person(lastname='Zosimo', firstname='Alice', age=43)}" |
| 1207 | + ] |
| 1208 | + }, |
| 1209 | + "execution_count": 53, |
| 1210 | + "metadata": {}, |
| 1211 | + "output_type": "execute_result" |
| 1212 | + } |
| 1213 | + ], |
| 1214 | + "source": [ |
| 1215 | + "people = {\n", |
| 1216 | + " Person(firstname='Alice', lastname='Zosimo', age=43),\n", |
| 1217 | + " Person(firstname='Aaron', lastname='Leibovitch', age=31),\n", |
| 1218 | + "}\n", |
| 1219 | + "people" |
| 1220 | + ] |
| 1221 | + }, |
| 1222 | + { |
| 1223 | + "cell_type": "markdown", |
| 1224 | + "id": "0133fe30-3973-4398-8c8d-e62bd504c519", |
| 1225 | + "metadata": {}, |
| 1226 | + "source": [ |
| 1227 | + "However, this implies you can not modify the objects." |
| 1228 | + ] |
| 1229 | + }, |
| 1230 | + { |
| 1231 | + "cell_type": "code", |
| 1232 | + "execution_count": 55, |
| 1233 | + "id": "37c2e8a4-2977-42b9-9529-30dfe1089f44", |
| 1234 | + "metadata": {}, |
| 1235 | + "outputs": [ |
| 1236 | + { |
| 1237 | + "name": "stdout", |
| 1238 | + "output_type": "stream", |
| 1239 | + "text": [ |
| 1240 | + "Person(lastname='Leibovitch', firstname='Aaron', age=31)\n", |
| 1241 | + "the objects is frozen\n", |
| 1242 | + "Person(lastname='Leibovitch', firstname='Aaron', age=31)\n" |
| 1243 | + ] |
| 1244 | + } |
| 1245 | + ], |
| 1246 | + "source": [ |
| 1247 | + "person = people.pop()\n", |
| 1248 | + "print(person)\n", |
| 1249 | + "try:\n", |
| 1250 | + " person.age = 12\n", |
| 1251 | + "except AttributeError:\n", |
| 1252 | + " print('the objects is frozen')\n", |
| 1253 | + "print(person)" |
| 1254 | + ] |
| 1255 | + }, |
| 1256 | + { |
| 1257 | + "cell_type": "markdown", |
| 1258 | + "id": "5554878d-ad20-4317-b58a-54c3c8958e2b", |
| 1259 | + "metadata": {}, |
| 1260 | + "source": [ |
| 1261 | + "This is of course fine if you do not need mutable ojbects. The alternative is to hash based on object identity." |
| 1262 | + ] |
| 1263 | + }, |
| 1264 | + { |
| 1265 | + "cell_type": "code", |
| 1266 | + "execution_count": 56, |
| 1267 | + "id": "f6269b27-ff89-40e8-bb85-5602cb0d6c72", |
| 1268 | + "metadata": {}, |
| 1269 | + "outputs": [], |
| 1270 | + "source": [ |
| 1271 | + "@attr.s(eq=False)\n", |
| 1272 | + "class Person:\n", |
| 1273 | + " lastname: str = attr.ib()\n", |
| 1274 | + " firstname: str = attr.ib()\n", |
| 1275 | + " age: int = attr.ib()\n", |
| 1276 | + " \n", |
| 1277 | + " @age.validator\n", |
| 1278 | + " def age_validator(self, attribute, value):\n", |
| 1279 | + " if value < 0 or value >= 130:\n", |
| 1280 | + " raise ValueError(f'age should be between 0 and 130')" |
| 1281 | + ] |
| 1282 | + }, |
| 1283 | + { |
| 1284 | + "cell_type": "markdown", |
| 1285 | + "id": "1e82961c-5ffb-43b4-b7e3-8e607beed8c7", |
| 1286 | + "metadata": {}, |
| 1287 | + "source": [ |
| 1288 | + "However, this implies that objects will be distinct, regardless of the values of their attributes." |
| 1289 | + ] |
| 1290 | + }, |
| 1291 | + { |
| 1292 | + "cell_type": "code", |
| 1293 | + "execution_count": 58, |
| 1294 | + "id": "4ca729cc-2ce4-470e-befd-bab544ae1f3c", |
| 1295 | + "metadata": {}, |
| 1296 | + "outputs": [ |
| 1297 | + { |
| 1298 | + "data": { |
| 1299 | + "text/plain": [ |
| 1300 | + "{Person(lastname='Leibovitch', firstname='Aaron', age=31),\n", |
| 1301 | + " Person(lastname='Leibovitch', firstname='Robert', age=49),\n", |
| 1302 | + " Person(lastname='Zosimo', firstname='Alice', age=43),\n", |
| 1303 | + " Person(lastname='Zosimo', firstname='Alice', age=43)}" |
| 1304 | + ] |
| 1305 | + }, |
| 1306 | + "execution_count": 58, |
| 1307 | + "metadata": {}, |
| 1308 | + "output_type": "execute_result" |
| 1309 | + } |
| 1310 | + ], |
| 1311 | + "source": [ |
| 1312 | + "people = {\n", |
| 1313 | + " Person(firstname='Alice', lastname='Zosimo', age=43),\n", |
| 1314 | + " Person(firstname='Aaron', lastname='Leibovitch', age=31),\n", |
| 1315 | + " Person(firstname='Robert', lastname='Leibovitch', age=49),\n", |
| 1316 | + " Person(firstname='Alice', lastname='Zosimo', age=43),\n", |
| 1317 | + "}\n", |
| 1318 | + "people" |
| 1319 | + ] |
| 1320 | + }, |
| 1321 | + { |
| 1322 | + "cell_type": "code", |
| 1323 | + "execution_count": 59, |
| 1324 | + "id": "086f2880-5772-4cd1-ba58-44576678d0b6", |
| 1325 | + "metadata": {}, |
| 1326 | + "outputs": [], |
| 1327 | + "source": [ |
| 1328 | + "alice1 = Person(firstname='Alice', lastname='Zosimo', age=43)\n", |
| 1329 | + "alice2 = Person(firstname='Alice', lastname='Zosimo', age=43)\n", |
| 1330 | + "alice3 = Person(firstname='alice', lastname='zosimo', age=43)" |
| 1331 | + ] |
| 1332 | + }, |
| 1333 | + { |
| 1334 | + "cell_type": "markdown", |
| 1335 | + "id": "ca98822f-691f-40a3-bb67-bbf989d87698", |
| 1336 | + "metadata": {}, |
| 1337 | + "source": [ |
| 1338 | + "`alice1` has the same attributes as `alice2`, but they are distinct objects nevertheless." |
| 1339 | + ] |
| 1340 | + }, |
| 1341 | + { |
| 1342 | + "cell_type": "code", |
| 1343 | + "execution_count": 60, |
| 1344 | + "id": "d5cb600d-f440-4919-9397-1e9b75af0d0f", |
| 1345 | + "metadata": {}, |
| 1346 | + "outputs": [ |
| 1347 | + { |
| 1348 | + "data": { |
| 1349 | + "text/plain": [ |
| 1350 | + "False" |
| 1351 | + ] |
| 1352 | + }, |
| 1353 | + "execution_count": 60, |
| 1354 | + "metadata": {}, |
| 1355 | + "output_type": "execute_result" |
| 1356 | + } |
| 1357 | + ], |
| 1358 | + "source": [ |
| 1359 | + "alice1 == alice2" |
| 1360 | + ] |
| 1361 | + }, |
| 1362 | + { |
| 1363 | + "cell_type": "code", |
| 1364 | + "execution_count": 61, |
| 1365 | + "id": "07a70926-54a2-425f-acb2-6aa22260f7c3", |
| 1366 | + "metadata": {}, |
| 1367 | + "outputs": [ |
| 1368 | + { |
| 1369 | + "data": { |
| 1370 | + "text/plain": [ |
| 1371 | + "False" |
| 1372 | + ] |
| 1373 | + }, |
| 1374 | + "execution_count": 61, |
| 1375 | + "metadata": {}, |
| 1376 | + "output_type": "execute_result" |
| 1377 | + } |
| 1378 | + ], |
| 1379 | + "source": [ |
| 1380 | + "alice1 is alice2" |
| 1381 | + ] |
| 1382 | + }, |
| 1383 | + { |
| 1384 | + "cell_type": "markdown", |
| 1385 | + "id": "1600b5e8-e10c-4eff-a369-87bc3920a8d3", |
| 1386 | + "metadata": {}, |
| 1387 | + "source": [ |
| 1388 | + "Of course, you can still impliment your own hash method and comparison methods if required." |
| 1389 | + ] |
1120 | 1390 | }
|
1121 | 1391 | ],
|
1122 | 1392 | "metadata": {
|
|
0 commit comments