@@ -27,15 +27,17 @@ The traditional programming paradigm (think Fortran, C, MATLAB, etc.) is called
2727It works as follows
28282929* The program has a state corresponding to the values of its variables.
30-* Functions are called to act on these data.
31-* Data are passed back and forth via function calls.
30+* Functions are called to act on and transform the state.
31+* Final outputs are produced via a sequence of function calls.
32323333Two other important paradigms are [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming) (OOP) and [functional programming](https://en.wikipedia.org/wiki/Functional_programming).
3434353536-In the OOP paradigm data and functions are "bundled together" into "objects" (and functions in this context are referred to as **methods**).
36+In the OOP paradigm, data and functions are bundled together into "objects" --- and functions in this context are referred to as **methods**.
373738-* think of a Python list that contains data and exposes methods such as `append()` and `count()`
38+Methods are called on to transform the data contained in the object.
39+40+* Think of a Python list that contains data and has methods such as `append()` and `pop()` that transform the data.
39414042Functional programming languages are built on the idea of composing functions.
4143@@ -55,7 +57,12 @@ By this we mean that, in Python, *everything is an object*.
55575658In this lecture, we explain what that statement means and why it matters.
575960+We'll make use of the following third party library
61+586263+```{code-cell} python3
64+!pip install rich
65+```
596660676168## Objects
@@ -200,7 +207,7 @@ These attributes are important, so let's discuss them in-depth.
200207201208Methods are *functions that are bundled with objects*.
202209203-Formally, methods are attributes of objects that are callable (i.e., can be called as functions)
210+Formally, methods are attributes of objects that are **callable** -- i.e., attributes that can be called as functions
204211205212```{code-cell} python3
206213x = ['foo', 'bar']
@@ -250,13 +257,82 @@ x
250257251258(If you wanted to you could modify the `__setitem__` method, so that square bracket assignment does something totally different)
252259260+## Inspection Using Rich
261+262+There's a nice package called [rich](https://github.com/Textualize/rich) that
263+helps us view the contents of an object.
264+265+For example,
266+267+```{code-cell} python3
268+from rich import inspect
269+x = 10
270+inspect(10)
271+```
272+If we want to see the methods as well, we can use
273+274+```{code-cell} python3
275+inspect(10, methods=True)
276+```
277+278+In fact there are still more methods, as you can see if you execute `inspect(10, all=True)`.
279+280+## A Little Mystery
281+282+In this lecture we claimed that Python is object oriented.
283+284+But here's an example that looks more procedural.
285+286+```{code-cell} python3
287+x = ['a', 'b']
288+m = len(x)
289+m
290+```
291+292+If Python is object oriented, why don't we use `x.len()`? Isn't this
293+inconsistent?
294+295+The answers are related to the fact that Python aims for consistent style.
296+297+In Python, it is common for users to build custom objects --- we discuss how to
298+do this [later](python_oop).
299+300+It's quite common for users to add methods to their that measure the length of
301+the object, suitably defined.
302+303+When naming such a method, natural choices are `len()` and `length()`.
304+305+If some users choose `len()` and others choose `length()`, then the style will
306+be inconsistent and harder to remember.
307+308+To avoid this, the creator of Python chose to have some built-in functions
309+like `len()`, to make clear that `len()` is the convention.
310+311+Now, having said all of this, Python still is object oriented under the hood.
312+313+In fact, the list `x` discussed above has a method called `__len__()`.
314+315+All that the function `len()` does is call this method.
316+317+In other words, the following code is equivalent:
318+319+```{code-cell} python3
320+x = ['a', 'b']
321+len(x)
322+```
323+and
324+325+```{code-cell} python3
326+x = ['a', 'b']
327+x.__len__()
328+```
329+253330254331## Summary
255332256-Messages in this lecture are clear:
333+The message in this lecture is clear:
257334258335* In Python, *everything in memory is treated as an object*.
259-* Zero, one or many names can be bound to a given object.
260336261337This includes not just lists, strings, etc., but also less obvious things, such as
262338@@ -291,47 +367,37 @@ You can use `callable()` to test whether an attribute of an object can be called
291367:class: dropdown
292368```
293369294-Firstly, we need to find all attributes of a boolean object.
295-296-You can use one of the following ways:
297-298-*1.* You can call the `.__dir__()` method
370+Firstly, we need to find all attributes of `True`, which can be done via
299371300372```{code-cell} python3
301373print(sorted(True.__dir__()))
302374```
303375304-*2.* You can use the built-in function `dir()`
376+or
305377306378```{code-cell} python3
307379print(sorted(dir(True)))
308380```
309381310-*3.* Since the boolean data type is a primitive type, you can also find it in the built-in namespace
382+Since the boolean data type is a primitive type, you can also find it in the built-in namespace
311383312384```{code-cell} python3
313385print(dir(__builtins__.bool))
314386```
315387316-Next, we can use a `for` loop to filter out attributes that are callable
388+Here we use a `for` loop to filter out attributes that are callable
317389318390```{code-cell} python3
319-attrls = dir(__builtins__.bool)
320-callablels = list()
391+attributes = dir(__builtins__.bool)
392+callablels = []
321393322-for i in attrls:
394+for attribute in attributes:
323395 # Use eval() to evaluate a string as an expression
324- if callable(eval(f'True.{i}')):
325- callablels.append(i)
396+ if callable(eval(f'True.{attribute}')):
397+ callablels.append(attribute)
326398print(callablels)
327399```
328400329-Here is a one-line solution
330-331-```{code-cell} python3
332-print([i for i in attrls if callable(eval(f'True.{i}'))])
333-```
334-335401336402```{solution-end}
337403```