Skip to content

Commit 18f83ab

Browse files
Main text adjustments
1 parent a5d39e7 commit 18f83ab

1 file changed

Lines changed: 67 additions & 66 deletions

File tree

‎Session 4 - Object-Oriented Programming I/Session 4 - Object-Oriented Programming I.ipynb‎

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
"metadata": {},
2929
"source": [
3030
"## What is meant by an `Object`\n",
31-
"The OOP programming paradigm is a modelling approach where the code is structured such that properties and behaviors are contained in individual objects.\n",
31+
"The OOP programming paradigm is a modeling approach where the code is structured such that properties and behaviors are contained in individual objects.\n",
3232
"\n",
33-
"Simple examples of objects we already been using:"
33+
"Simple examples of objects we have already been using:"
3434
]
3535
},
3636
{
@@ -104,11 +104,14 @@
104104
"cell_type": "markdown",
105105
"metadata": {},
106106
"source": [
107-
"So when we define a string, float, integer, boolean, list etc. in Python we're actually initiating objects (instances of the respective classes).\n",
108-
"Beside storing information, these objects also contains a set of behavioural operations (method calls) relevant for the specific object. \n",
107+
"So when we define a string, float, integer, boolean, list etc. in Python we're actually **initiating objects** (instances of the respective classes).\n",
108+
"Beside storing information, these objects also contains a set of **behavioral operations** (method calls) relevant for the specific object. \n",
109109
"\n",
110-
"With functional programming you would have had to define all these methods as individual functions (poluting the namespace) and also name them so it's clear what type of variables they're intended for. With OOP you can integrate these into each of the specific object types, making them only accessible right where you may need them.\n",
111-
"The methods names can also be simpler as it is obvious which data type they're intended for and it can be made more readable (e.g. my_float.as_integer_ratio()). But most importantely, you're encouraged to split your problem into logical entities/objects and bind any behavioural function-like features to these objects which results in an intuitive structure easy to use/build upon by others."
110+
"With functional programming you would have had to define all these methods as individual functions (polluting the namespace) and also name them so it's clear what type of variables they're intended for. With OOP you can integrate these into each of the specific object types, making them only accessible right where you may need them.\n",
111+
"\n",
112+
"The method names can also be simpler as it is obvious which data type they're intended for and it can be made more readable (e.g. `my_float.as_integer_ratio()`). \n",
113+
"\n",
114+
"**But most importantly, using OOP encourages you to split your problem into logical entities/objects and bind any behavioral function-like features to these objects which results in an intuitive structure that is easy to use and build upon by others.**"
112115
]
113116
},
114117
{
@@ -122,20 +125,21 @@
122125
"cell_type": "markdown",
123126
"metadata": {},
124127
"source": [
125-
"When dealing with OOP there's four terms one needs to understand:\n",
128+
"When dealing with OOP there are four terms one needs to understand:\n",
126129
"- class\n",
127130
"- instance\n",
128131
"- method\n",
129132
"- attribute\n",
130133
"\n",
131-
"A `class` is at its essence an user-defined data structure with fully customizable behaviours. It's the blueprint describing the information structure and any corresponding behavial operations for any objects/instances created from it.\n",
132-
"The `float class` e.g. describes the data structure for being able to store a signed decimal number together with definition of any behavioural operations/method calls relevant for floats.\n",
133-
"It will never contain a specific floating number!\n",
134+
"A `class` is at its essence a user-defined data structure with fully customizable behaviors. It's the blueprint describing the information structure and any corresponding behavioral operations for any objects/instances created from it.\n",
135+
"The `float class` e.g. describes the data structure for being able to store a signed decimal number together with definition of any behavioral operations/method calls relevant for floats.\n",
136+
"The class itself will never contain a specific floating number!\n",
134137
"\n",
135-
"From any class an infinite number of `instance` can be initiated. While the class containes the blueprint, instances are the actual objects created from a class.\n",
138+
"From any class an infinite number of `instances` can be initiated. While the class contains the blueprint, instances are the actual objects created from a class.\n",
136139
"'my_float', 'my_string', 'my_list' are all instances/actual objects made using the blueprint defined by the corresponding classes.\n",
140+
"So while the `float class` from above will never contain a specific floating number, `instances` of the class can be created to represent specific floating point numbers. \n",
137141
"\n",
138-
"A `method` is a function-like operation, defined by the class, but available to be called from any instances initiated from the class. Just like with functions methods are also executed by having a bracket after the method name containg possible input arguments.\n",
142+
"A `method` is a function-like operation defined by and tied to the class. Methods are available to be called from any instances initiated from the class. Just like with functions, methods are also executed by having a bracket after the method name containing possible input arguments.\n",
139143
"\n",
140144
"Finally, an `attribute` refers to some information/value (a property) stored in an object. To access an attribute of an object you do not have a bracket after the attribute name as it does not need to be executed."
141145
]
@@ -176,15 +180,16 @@
176180
"metadata": {},
177181
"outputs": [],
178182
"source": [
179-
"# Defining a 'Rectangle' class\n",
180183
"class Rectangle:\n",
184+
" '''Defining a 'Rectangle' class.'''\n",
181185
" \n",
182-
" # This is a special constructor method that initialise the object\n",
183186
" def __init__(self, height, width):\n",
187+
" '''This is a special constructor method that initializes the object.'''\n",
184188
" self.height = height\n",
185189
" self.width = width\n",
186190
" \n",
187191
" def calculate_area(self):\n",
192+
" '''Return the area of the rectangle.'''\n",
188193
" area = self.height * self.width\n",
189194
" return area"
190195
]
@@ -193,7 +198,7 @@
193198
"cell_type": "markdown",
194199
"metadata": {},
195200
"source": [
196-
"The `__init__` method is a special method that is executed when a new instance/object is initialised.\n",
201+
"The `__init__` method is a special method that is executed when a new instance/object is initialized.\n",
197202
"\n",
198203
"The `self` is a placeholder object for the instance object not yet created during the class definition."
199204
]
@@ -217,7 +222,7 @@
217222
"name": "stdout",
218223
"output_type": "stream",
219224
"text": [
220-
"<__main__.Rectangle object at 0x0000024D9593C518>\n"
225+
"<__main__.Rectangle object at 0x0000022EC29BADC8>\n"
221226
]
222227
}
223228
],
@@ -270,7 +275,7 @@
270275
"metadata": {},
271276
"source": [
272277
"Notice how you don't have to input the `self` argument when the method is executed from an instance.\n",
273-
"However, same result can also be obtained by executing the method directly from thee class definition, but this time ginving the instance to be considered as the 'self' input."
278+
"However, same result can also be obtained by executing the method directly from thee class definition, but this time giving the rectangle instance *itself* to be considered as the `self` input."
274279
]
275280
},
276281
{
@@ -313,35 +318,47 @@
313318
"metadata": {},
314319
"outputs": [],
315320
"source": [
316-
"# Defining a 'Rectangle' class\n",
317321
"class Rectangle:\n",
318-
" no_corners = 4 # this is a class variable that applies to all rectangles\n",
322+
" ''' Defining a 'Rectangle' class.'''\n",
323+
" \n",
324+
" num_corners = 4 # this is a class variable that applies to all rectangles\n",
319325
" \n",
320326
" def __init__(self, height, width):\n",
321327
" self._height = height # this is a protected attribute\n",
322328
" self._width = width # this is a protected attribute\n",
323329
" self.__area = None # this is a private attribute\n",
324330
" \n",
325331
" def get_area(self):\n",
326-
" # check if _area have been updated\n",
332+
" '''Return the area of the rectangle if present, if not compute it and return it.'''\n",
333+
" # check if __area have been updated\n",
327334
" if not self.__area:\n",
328335
" self.__area = Rectangle.calculate_area(self._height, self._width)\n",
329336
" return self.__area\n",
330337
" \n",
331338
" # a static method is independent of an instance and is defined by the corresponding decorator\n",
332339
" @staticmethod\n",
333340
" def calculate_area(height, width):\n",
341+
" '''Compute and return the area of the rectangle.'''\n",
334342
" area = height * width\n",
335343
" return area"
336344
]
337345
},
346+
{
347+
"cell_type": "markdown",
348+
"metadata": {},
349+
"source": [
350+
"Notice the *class variable* `num_corners`, which is defined *before* the `__init__` method. \n",
351+
"Recall that the `__init__` method is used to initialize each specific instance, i.e. all types of rectangles that might be created. By defining the class variable before the initialization of each unique instance, it will be assigned to all instances of a class that are created.\n",
352+
"This makes sense since all rectangles are bound to have four corners."
353+
]
354+
},
338355
{
339356
"cell_type": "code",
340357
"execution_count": 11,
341358
"metadata": {},
342359
"outputs": [],
343360
"source": [
344-
"# Initialise new rectangle instance\n",
361+
"# Initialize new rectangle instance\n",
345362
"rect2 = Rectangle(height=10, width=3)"
346363
]
347364
},
@@ -367,15 +384,15 @@
367384
}
368385
],
369386
"source": [
370-
"print('Number of corners:', rect2.no_corners) # ask for number of corners\n",
387+
"print('Number of corners:', rect2.num_corners) # ask for number of corners\n",
371388
"print('the area is: ', rect2.get_area()) # get area"
372389
]
373390
},
374391
{
375392
"cell_type": "markdown",
376393
"metadata": {},
377394
"source": [
378-
"A static method can be used, directly from the class, without having to initialise an instance.\n",
395+
"A static method can be used, directly from the class, without having to initialize an instance.\n",
379396
"This is useful if one wants to use a class also as a container for related functions which may even be used by the methods like here."
380397
]
381398
},
@@ -472,6 +489,13 @@
472489
"print('__area attribute:', rect2.__area)"
473490
]
474491
},
492+
{
493+
"cell_type": "markdown",
494+
"metadata": {},
495+
"source": [
496+
"As seen, they cannot be accessed directly from outside the class definition."
497+
]
498+
},
475499
{
476500
"cell_type": "markdown",
477501
"metadata": {},
@@ -481,35 +505,19 @@
481505
},
482506
{
483507
"cell_type": "code",
484-
"execution_count": 17,
508+
"execution_count": null,
485509
"metadata": {},
486-
"outputs": [
487-
{
488-
"name": "stdout",
489-
"output_type": "stream",
490-
"text": [
491-
"available attributes: ['_Rectangle__area', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_height', '_width', 'calculate_area', 'get_area', 'no_corners']\n"
492-
]
493-
}
494-
],
510+
"outputs": [],
495511
"source": [
496512
"# list all available attributes\n",
497513
"print('available attributes:', dir(rect2))"
498514
]
499515
},
500516
{
501517
"cell_type": "code",
502-
"execution_count": 18,
518+
"execution_count": null,
503519
"metadata": {},
504-
"outputs": [
505-
{
506-
"name": "stdout",
507-
"output_type": "stream",
508-
"text": [
509-
"_Rectangle__area: 999\n"
510-
]
511-
}
512-
],
520+
"outputs": [],
513521
"source": [
514522
"rect2._Rectangle__area = 999\n",
515523
"print('_Rectangle__area:', rect2._Rectangle__area)"
@@ -524,17 +532,9 @@
524532
},
525533
{
526534
"cell_type": "code",
527-
"execution_count": 19,
535+
"execution_count": null,
528536
"metadata": {},
529-
"outputs": [
530-
{
531-
"name": "stdout",
532-
"output_type": "stream",
533-
"text": [
534-
"_Rectangle__private: my default value\n"
535-
]
536-
}
537-
],
537+
"outputs": [],
538538
"source": [
539539
"# getattr allows for providing a default return when attribute does not exist\n",
540540
"print('_Rectangle__private:', getattr(rect2, '__private', 'my default value'))"
@@ -551,17 +551,18 @@
551551
"cell_type": "markdown",
552552
"metadata": {},
553553
"source": [
554-
"Let's now try to build a rectangle that support get(s) and set(s) of all properties: height, width and area"
554+
"Let's now try to build a rectangle class that supports get(s) and set(s) of all properties: height, width and area."
555555
]
556556
},
557557
{
558558
"cell_type": "code",
559-
"execution_count": 20,
559+
"execution_count": 17,
560560
"metadata": {},
561561
"outputs": [],
562562
"source": [
563-
"# Defining a 'Rectangle' class\n",
564563
"class Rectangle:\n",
564+
" '''Defining a 'Rectangle' class.'''\n",
565+
" \n",
565566
" __slots__ = ('height', 'width') # predefine allowable/possible attributes\n",
566567
" \n",
567568
" def __init__(self, height, width):\n",
@@ -587,11 +588,11 @@
587588
},
588589
{
589590
"cell_type": "code",
590-
"execution_count": 21,
591+
"execution_count": 18,
591592
"metadata": {},
592593
"outputs": [],
593594
"source": [
594-
"# Initialise new rectangle instance\n",
595+
"# Initialize new rectangle instance\n",
595596
"rect3 = Rectangle(height=12, width=6)\n",
596597
"rect4 = Rectangle(height=20, width=4)"
597598
]
@@ -605,7 +606,7 @@
605606
},
606607
{
607608
"cell_type": "code",
608-
"execution_count": 22,
609+
"execution_count": 19,
609610
"metadata": {},
610611
"outputs": [
611612
{
@@ -625,7 +626,7 @@
625626
},
626627
{
627628
"cell_type": "code",
628-
"execution_count": 23,
629+
"execution_count": 20,
629630
"metadata": {},
630631
"outputs": [
631632
{
@@ -642,7 +643,7 @@
642643
},
643644
{
644645
"cell_type": "code",
645-
"execution_count": 24,
646+
"execution_count": 21,
646647
"metadata": {},
647648
"outputs": [
648649
{
@@ -651,13 +652,13 @@
651652
"True"
652653
]
653654
},
654-
"execution_count": 24,
655+
"execution_count": 21,
655656
"metadata": {},
656657
"output_type": "execute_result"
657658
}
658659
],
659660
"source": [
660-
"# compare rectangles with high readability\n",
661+
"# compare rectangle areas with high readability\n",
661662
"rect3.area < rect4.area"
662663
]
663664
},
@@ -692,7 +693,7 @@
692693
},
693694
{
694695
"cell_type": "code",
695-
"execution_count": 19,
696+
"execution_count": 22,
696697
"metadata": {},
697698
"outputs": [
698699
{
@@ -965,7 +966,7 @@
965966
"<IPython.core.display.HTML object>"
966967
]
967968
},
968-
"execution_count": 19,
969+
"execution_count": 22,
969970
"metadata": {},
970971
"output_type": "execute_result"
971972
}
@@ -994,7 +995,7 @@
994995
"name": "python",
995996
"nbconvert_exporter": "python",
996997
"pygments_lexer": "ipython3",
997-
"version": "3.7.3"
998+
"version": "3.7.6"
998999
},
9991000
"latex_envs": {
10001001
"LaTeX_envs_menu_present": true,

0 commit comments

Comments
 (0)