GitHub

@@ -27,15 +27,17 @@ The traditional programming paradigm (think Fortran, C, MATLAB, etc.) is called

2727

It 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.

32323333

Two 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.

39414042

Functional 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*.

55575658

In 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.

200207201208

Methods 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

206213

x = ['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.

260336261337

This 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

301373

print(sorted(True.__dir__()))

302374

```

303375304-

*2.* You can use the built-in function `dir()`

376+

or

305377306378

```{code-cell} python3

307379

print(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

313385

print(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)

326398

print(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

```

Read the original on github.com ↗