Skip to content

Commit 8440e9b

Browse files
committed
Classes reorganization
1 parent 152222c commit 8440e9b

File tree

13 files changed

+82
-716
lines changed

13 files changed

+82
-716
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ has_children: true
44
nav_order: 9
55
---
66

7-
# Classes and Objects
7+
# Classes and Objects: Basis

09 Classes and Objects/1 A problem.md renamed to 09 Classes and Objects Basis/1 A problem.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
parent: Classes and Objects
2+
parent: "Classes and Objects: Basis"
33
grand_parent: Programming for Modelling and Data Analysis
44
nav_order: 1
55
---

09 Classes and Objects/2 Classes and objects to organize your code.md renamed to 09 Classes and Objects Basis/2 Classes and objects.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
2-
parent: Classes and Objects
2+
parent: "Classes and Objects: Basis"
33
grand_parent: Programming for Modelling and Data Analysis
44
nav_order: 2
55
---
66

7-
# Classes and objects to organize your code
7+
# Classes and objects
88

99
The problem described in the previous chapter can be summarized as follows: how to combine together all the variables describing each player's state and how to operate on them. Python has neat solution for this using a concept of classes and objects. Classes are general concepts of an entity, its state and what it can do (in our case this will be **a** player), while objects are specific instances of these concepts (**the** players: *Alfred*, *Beatrice*, *Charlie*).
1010

@@ -81,7 +81,7 @@ class Player:
8181

8282

8383
def ask(player):
84-
# This function is part on the input-output,
84+
# This function is part of the input-output,
8585
# so it should not be in the `Player` class
8686
while True:
8787
answer = input(f"{player.name}, do you want to keep rolling? [y/n]: ").lower()
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
parent: "Classes and Objects: Basis"
3+
grand_parent: Programming for Modelling and Data Analysis
4+
nav_order: 3
5+
---
6+
7+
# Custom data types
8+
9+
Looking at **objects** and **classes**, you might have noticed a similarity with **variables** and their **types**. In fact this is exactly the same. By defining a class, you create a new type and a class instance is simply a variable of this type. Built-in Python types are also classes. Notice that you have already used their methods:
10+
11+
```python
12+
name = "python"
13+
print(name.upper()) # `upper()` is a method in `str` class
14+
```
15+
16+
You may define any type you want. Consider a class defining a fraction. It should have two attributes, *nominator* (named shortly `nom`) and *denominator* (`denom`):
17+
18+
```python
19+
class Fraction:
20+
def __init__(self, nom, denom):
21+
self.nom = nom
22+
self.denom = denom
23+
```
24+
25+
It is possible to perform mathematical operations on fractions, like addition, subtraction, multiplication and division. Let's define a function `mul` that takes two fractions, multiplies them, and returns a `Fraction` instance, which is their factor:
26+
27+
```python
28+
def mul(a, b):
29+
return Fraction(a.nom * b.nom, a.denom * b.denom)
30+
```
31+
32+
Actually this function is specific for fractions only. So, in order to keep things together, it is better to make it a method in a fraction:
33+
34+
```python
35+
class Fraction:
36+
def __init__(self, nom, denom):
37+
self.nom = nom
38+
self.denom = denom
39+
40+
def mul(self, other):
41+
return Fraction(self.nom * self.nom, self.denom * self.denom)
42+
```
43+
44+
We may use this method as follows:
45+
46+
```python
47+
x = Fraction(1, 2)
48+
y = Fraction(5, 6)
49+
50+
z = x.mul(y)
51+
```
52+
53+
The last line does not look good. Later in this course, you will learn what you can do to be able to use normal mathematical operators (`z = x * y`) for your classes.
54+
55+
<hr/>
56+
57+
Published under [Creative Commons Attribution-NonCommercial-ShareAlike](https://creativecommons.org/licenses/by-nc-sa/4.0/) license.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ def roll(self):
1818
return dice, score
1919

2020

21-
# This function is part on the input-output, so it should not be in the `Player` class
2221
def ask(player):
22+
# This function is part of the input-output,
23+
# so it should not be in the `Player` class
2324
while True:
2425
answer = input(f"{player.name}, do you want to keep rolling? [y/n]: ").lower()
2526
if answer in 'yn':

09 Classes and Objects/3 Custom data types.md

Lines changed: 0 additions & 175 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ has_children: true
44
nav_order: 11
55
---
66

7-
# Object-Oriented Programming
7+
# Classes and Objects: Intermediate

09 Classes and Objects/4 Special methods.md renamed to 11 Classes and Objects Intermediate/1 Special methods.md

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
11
---
2-
parent: Classes and Objects
2+
parent: "Classes and Objects: Intermediate"
33
grand_parent: Programming for Modelling and Data Analysis
4-
nav_order: 4
4+
nav_order: 1
55
---
66

77
# Special methods
88

99
## Arithmetical operations
1010

11-
Consider a class defining a fraction. It should have two attributes, *nominator* (named shortly `nom`) and *denominator* (`denom`):
12-
13-
```python
14-
class Fraction:
15-
def __init__(self, nom, denom):
16-
self.nom = nom
17-
self.denom = denom
18-
```
19-
20-
It is possible to perform mathematical operations on fractions, like addition, subtraction, multiplication and division. Let's define a function `mul` that takes two fractions, multiplies them, and returns a `Fraction` instance, which is their factor:
21-
22-
```python
23-
def mul(a, b):
24-
return Fraction(a.nom * b.nom, a.denom * b.denom)
25-
```
26-
27-
Actually this function is specific for fractions only. So, in order to keep things together, it is better to make it a method in a fraction:
11+
Let's go back to our [`Fraction` class](../09%20Classes%20and%20Objects%20Basis/3%20Custom%20data%20types):
2812

2913
```python
3014
class Fraction:
@@ -36,16 +20,7 @@ class Fraction:
3620
return Fraction(self.nom * self.nom, self.denom * self.denom)
3721
```
3822

39-
We may use this method as follows:
40-
41-
```python
42-
x = Fraction(1, 2)
43-
y = Fraction(5, 6)
44-
45-
z = x.mul(y)
46-
```
47-
48-
The last line does not look good. It would be much more clear if we were able to write `c = a * b`. In fact we can. Let's rename the method `mul` to `__mul__` (two underscored in the beginning and the end, like in `__init__`):
23+
Such formulation allows us to multiply two fractions in an ugly way `c = a.mul(b)`. It would be much more clear if we were able to write `c = a * b`. In fact we can. Let's rename the method `mul` to `__mul__` (two underscored in the beginning and the end, like in `__init__`):
4924

5025
```python
5126
class Fraction:
@@ -63,7 +38,7 @@ Now we can write:
6338
x = Fraction(1, 2)
6439
y = Fraction(5, 6)
6540

66-
z = a * b
41+
z = x * y
6742
```
6843

6944
Methods with two underscores in the beginning and the end are [*special methods*](https://diveintopython3.net/special-method-names.html). Generally you never invoke them directly. For example, you never call the `__init__` method explicitly. It is automatically invoked on instance creation. `__mul__` is another such method and it is called when two objects are multiplied.
@@ -155,7 +130,7 @@ Some other special functions that are very useful are comparisons. Fractions can
155130
> class Fraction:
156131
> def __init__(self, nom, denom):
157132
> r = gcd(nom, denom)
158-
> self.nom = nom // r # we use // for integer division
133+
> self.nom = nom // r # we use // for integer division
159134
> self.denom = denom // r
160135
>
161136
> def __str__(self):
@@ -167,9 +142,6 @@ Some other special functions that are very useful are comparisons. Fractions can
167142
>
168143
> Also in the constructor you can do more sanitizations, like checking if the denominator is not 0 (and raising `ValueError` in such case), making sure that the denominator is always positive (and the sign of the nominator is adjusted accordingly), etc.
169144
170-
171-
172-
173145
<hr/>
174146
175147
Published under [Creative Commons Attribution-NonCommercial-ShareAlike](https://creativecommons.org/licenses/by-nc-sa/4.0/) license.

11 Object-Oriented Programming/3 Understanding class inheritance.md renamed to 11 Classes and Objects Intermediate/2 Class inheritance.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
parent: Object-Oriented Programming
2+
parent: "Classes and Objects: Intermediate"
33
grand_parent: Programming for Modelling and Data Analysis
4-
nav_order: 3
4+
nav_order: 2
55
---
66

77
# Understanding Class Inheritance

0 commit comments

Comments
 (0)