Skip to content

Commit 0dc3d25

Browse files
committed
Add more descriptions for classes
1 parent 41daaf7 commit 0dc3d25

File tree

4 files changed

+177
-0
lines changed

4 files changed

+177
-0
lines changed

docs/ch03-02-scopes.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# スコープ
2+
3+
他の言語ではクラスメンバに対して `public, protected, private` といったアクセス指定子を指定することができますが Python ではそのような指定はできず、すべてのメンバが `public` として扱われます。ですが習慣的に下記のような命名規則でメンバのスコープを区別するようになっています。
4+
5+
| スコープ | 命名規則 |
6+
|-----------|--------------|
7+
| public | `method()` |
8+
| protected | `_method()` |
9+
| private | `__method()` |
10+
11+
Python では `__method()` のような private メソッドを作ることはそれほど多くはありません。隠蔽したいメンバを定義するときは `_method()` のような protected メソッドを定義することのほうが多いです。

docs/ch03-03-special-attributes.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# 特殊属性
2+
3+
新たなクラスを定義したときには自動で定義されるメンバやメソッドが存在しており、それらを特殊属性といいます。代表的な特殊属性をいくつか紹介します。
4+
5+
下記のようなクラスを定義したときの特殊属性には次のようなものがあります。
6+
7+
```python
8+
import math
9+
10+
11+
class Point:
12+
"""Point クラスです。"""
13+
14+
def __init__(self, x, y):
15+
self.x = x
16+
self.y = y
17+
18+
def distance(self):
19+
return math.sqrt(self.x * self.x + self.y * self.y)
20+
```
21+
22+
## `__doc__`
23+
24+
`Point.__doc__` という変数には `"""Point クラスです。"""` という文字列が入ります。`""" ... """` というトリプルクオテーションでくくられた文字列は改行を含む複数行の文字列を定義できる文字列です。
25+
26+
```python
27+
"""この文字列は
28+
一つの文字列として
29+
扱われます。"""
30+
```
31+
32+
`__doc__` は docstring と呼ばれ、ドキュメンテーションをする際に使用される文字列として扱われます。
33+
34+
## `__init__`
35+
36+
クラスインスタンスを作成するときは `__init__()` が呼び出されます。
37+
38+
```python
39+
point = Point(10, 20) # point.__init__(10, 20)
40+
```
41+
42+
## `__getattribute__`
43+
44+
クラスのメンバやメソッドを参照したときは `__getattribute__()` が呼び出されます。
45+
46+
```python
47+
point = Point(10, 20)
48+
point.x # point.__getattribute__('x')
49+
point.distance() # point.__getattribute__('distance')()
50+
```
51+
52+
## `__getattr__`
53+
54+
`__getattribute__()` でのメンバ参照に失敗した場合は `__getattr__()` が呼び出されます。このような事が起こるのはクラスのメンバとして定義されていないものにアクセスしようとしたときに起こります。
55+
56+
```python
57+
point.foo # point.__getattr__('foo')
58+
```
59+
60+
## `__setattr__`
61+
62+
メンバへの代入が行われた場合は `__setattr__()` が呼び出されます。
63+
64+
```python
65+
point = Point(10, 20)
66+
point.x = 30 # point.__setattr__('x', 30)
67+
```
68+
69+
## `__eq__`
70+
71+
インスタンスに対して `==` が使用された場合は `__eq__()` が呼ばれます。
72+
73+
```python
74+
point1 = Point(10, 20)
75+
point2 = Point(30, 40)
76+
point1 == point2 # point1.__eq__(point2)
77+
```
78+
79+
その他類似の特殊属性が下記の通り用意されています。
80+
81+
| 特殊属性 | 意味 |
82+
|----------|--------------------|
83+
| `__ne__` | `point1 != point2` |
84+
| `__le__` | `point1 <= point2` |
85+
| `__lt__` | `point1 < point2` |
86+
| `__ge__` | `point1 >= point2` |
87+
| `__gt__` | `point1 > point2` |

docs/ch03-04-properties.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# プロパティ
2+
3+
クラスのメンバで変数のように参照することのできる関数のことをプロパティといいます。
4+
5+
```python
6+
import math
7+
8+
9+
class Point:
10+
def __init__(self, x, y):
11+
self.x = x
12+
self.y = y
13+
14+
@property
15+
def distance(self):
16+
return math.sqrt(self.x * self.x + self.y * self.y)
17+
```
18+
19+
`@property` のように `@` ではじまるキーワードは **デコレータ** といって関数やクラスに特殊な振る舞いを注入することのできる機能になっています。`distance()` は関数として定義されていますが `@property` デコレータがついていると変数のように参照することができるようになります。
20+
21+
```python
22+
point = Point(10, 20)
23+
point.distance # 22.360679775
24+
```
25+
26+
プロパティは `point.distance()` のように呼ぶことはできません。
27+
28+
メンバ変数 `x, y` を隠蔽して、代わりにプロパティを提供すると代入ができなくなるので安全です。
29+
30+
```python
31+
import math
32+
33+
34+
class Point:
35+
def __init__(self, x, y):
36+
# _ をつけて隠蔽していることを示す
37+
self._x = x
38+
self._y = y
39+
40+
@property
41+
def x(self):
42+
return self._x
43+
44+
@property
45+
def y(self):
46+
return self._y
47+
48+
@property
49+
def distance(self):
50+
return math.sqrt(self.x * self.x + self.y * self.y)
51+
```
52+
53+
```python
54+
point = Point(10, 20)
55+
print(point.x, point.y) # _x, _y の参照は可能
56+
point.x = 30 # _x, _y への代入はできない
57+
```
58+
59+
プロパティに対して代入を行いたい場合は `setter` プロパティを定義します。
60+
61+
```python
62+
@property
63+
def x(self):
64+
return self._x # getter
65+
66+
@x.setter
67+
def x(self, value):
68+
self._x = value # setter
69+
```
70+
71+
72+
```python
73+
point.x = 30 # OK
74+
```
75+
76+
プロパティの利点は `get_x()` のような関数を定義しなくても、まるで変数を直接参照しているようなコードが書ける点にあります。これはクラスを利用する人からするとシンプルなコードが書けるので便利です。ただしプロパティは変数と同じくらいに気軽に参照するメンバになるので、パフォーマンスが遅い関数をむやみにプロパティとして定義するのは避けたほうが良いです。

mkdocs.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ nav:
5656
- 2.7. ラムダ式: ch02-07-lambdas.md
5757
- 3. クラス:
5858
- 3.1. クラス: ch03-01-classes.md
59+
- 3.2. スコープ: ch03-02-scopes.md
60+
- 3.3. 特殊属性: ch03-03-special-attributes.md
61+
- 3.4. プロパティ: ch03-04-properties.md
5962
- 4. モジュールとパッケージ:
6063
- 4.1. モジュール: ch04-01-modules.md
6164
- 4.2. パッケージ: ch04-02-packages.md

0 commit comments

Comments
 (0)