Python の len 関数の意味とメソッではなく関数である理由

len はオブジェクトの数を
かぞえています。
メソッドよりも関数が
読みやすいからです。

len の意味

len はオブジェクトの数を
かぞえています。

はじめて len を見たとき、いまいちこれが何を意味しているかわかりませんでした。 たしかに文字列のときは  文字列の長さ  なのですが、辞書やリストのときは  オブジェクトの数  だったりします。 どちらかというと要素数の方が使われ方としては多い気がします。

len 関数を引数に取ることができるオブジェクト

len 関数を引数に取ることができるオブジェクトの一覧です。

# 個数
<class 'dict'>
<class 'set'>
<class 'frozenset'>
<class 'tuple'>
<class 'list'>
<class 'range'>

# 長さ
<class 'str'>
<class 'bytes'>
<class 'bytearray'>

# よく分からない。今回は保留します。
<class 'memoryview'>

実際のところ str, bytes, bytearray も各要素にオブジェクトを保存しているので、 オブジェクトの数という理解でいいかなと思ったりもします。

str は  Unicode のコードポイントの集まり  で len はコードポイントの個数を数えています。 bytes は数字の集まりで len は数字の個数を数えています。 bytearray はミュータブルな bytes です、こちらも同じく len は数字の個数を数えています。

実際、添字表記で1つ1つのオブジェクトを参照することができます。 このようにして添字表記で参照できるオブジェクトをシーケンスと読んだりします。

s = 'こんにちは'
s[0]  # 'こ'

b = s.encode('utf-8')
b[0]  # 227

a = bytearray(b)
a[0]  # 227

上のコードを見ると 'こんにちは' を utf-8 に変換しているのに utf-8 じゃなくてなんで数字なの?みたいな疑問もあるかと思います。 str, bytes, bytearray の違いについては、また別に機会にご紹介させてください。

再度整理すると次のような感じになります。

# 個数
<class 'dict'>
<class 'set'>
<class 'frozenset'>
<class 'tuple'>
<class 'list'>
<class 'range'>
<class 'str'>
<class 'bytes'>
<class 'bytearray'>

# よく分からない。今回は保留します。
<class 'memoryview'>

色々な考え方、見方はありますが len はオブジェクトの個数を表していると考えると、 気持ち的にスッキリします。 len とかじゃなくて count を略して cnt とかでもよかったんじゃないかなと思います...。

どうやって一覧を取り出したの?

len 関数は、実際には __len__ メソッドを呼び出しているだけです。

# 対話モード >>> に
# コピペで実行できます。

lst = [0, 1, 2]

len(lst)
# 3

lst.__len()__
# 3

len 関数は、実際には __len__ メソッドを呼び出しているだけなので、 __len__ メソッドを定義してあげれば、ユーザ定義クラスでも len を使うことができます。

# 対話モード >>> に
# コピペで実行できます。
class Cls:
    def __len__(self):
        return 1

len(Cls())  # 1

__len__ メソッドを持つ「組み込み型」を取得できれば、 len 関数が引数に取ることができるクラスの一覧を取り出せます。 「組み込み型」は 「built-in スコープ」 にはいっているので、 これを利用します。

# len が使える組み込み型を取り出して見ます。
# 対話モード >>> にコピペで実行できます。

# 1. __builtins__    built-in スコープの名前空間です。
# 2. isinstance 関数 オブジェクトがクラスに属するか判定します。
# 3. hasattr 関数    オブジェクトが属性を持つか判定します。

builtin_types = []
for obj in __builtins__.__dict__.values():
    if isinstance(obj, type) and hasattr(obj, '__len__'):
        builtin_types.append(cls)

# あとは表示するだけ
print(*builtin_sized_types, sep='\n')
>>> print(*builtin_sized_types, sep='\n')
<class 'memoryview'>
<class 'bytearray'>
<class 'bytes'>
<class 'dict'>
<class 'frozenset'>
<class 'list'>
<class 'range'>
<class 'set'>
<class 'str'>
<class 'tuple'>
>>>

len がメソッドではなく関数である理由

メソッドよりも関数が
読みやすいからです。

メソッドよりも関数が読みやすいからです。 Guido は次の2つの理由を挙げています。 まず第一に接頭辞よりも接尾辞の方がわかりやすいから。 また第二に len という処理に対してインターフェイスを統一することができるから。

ちなみに Go 言語でも同様の理由で、len がメソッドではなく関数で定義されています。 以下の記事は Go 言語に関する記事です。

我々はこの問題を議論しましたが、 len とその類を関数として実装することにしたのは、 実際その方が優れていることと、  基本的な型が実装しているインタフェースを複雑にしないため  です。
lenが、メソッドでなく関数である理由は? - golang.jp


実際 __len__ を定義して int 以外の型を返そうとすると、例外を投げ返されます。 こうやってインターフェイスが統一されているんですね。

class Cls:
    def __len__(self):
        return 'Hello, world!'

len(Cls())  # TypeError
>>> len(Cls())  # 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object cannot be interpreted as an integer
>>> 

このあと、まず疑問を提示し、次に、それに答える形で Guido のメールを引用します。 そして Guido のメールに解説を加えていきます。

関数とメソッドを比較する。

1. 関数

Python では __len__ メソッドを定義すると、 そのクラスのインスタンスは len 関数で使えるようになります。

class Cls:
    def __len__(self):
        return 1

obj = Cls()
len(obj)  # 1

2. メソッド

でも、最初から len メソッド定義すればよくない? と思ってしまうわけです。

class Cls:
    def len(self):
        return 1

obj = Cls()
obj.len()  # 1

min, max が関数として定義されているのは、わかります。 max, min 関数は iterable なオブジェクトを引数に取ります。 for 文で繰り返すことができるオブジェクトを iterable と言います。 例えば、range, list, tuple, dict などが該当します。

for element in iterable:
    print(element)

たとえ、そのオブジェクトがどのクラスであったとしても、iterable であるならば処理は同じです。 クラスごとにメソッドを定義するのはどう考えても冗長ですから、処理を関数で一箇所にまとめるのが妥当でしょう。

でも len は違います。len の実装はクラスごとに異なります。1つの関数にまとめることはできないはずです。 それを無理やり各クラスごとに __len__ メソッドを定義して、len 関数で呼び出しています。

繰り返しになりますが len 関数は __len__ メソッドを呼び出ししているだけです。 それなら上のような実装でよくないのかなとも思ってしまうのです。

このような実装は2つの欠点があると思います。まず、第一にメソッドで書いたり、 関数で書いたりして、一貫性が損なわれているような気もします。 また、第二に無理やりメソッドではなく関数で呼び出すような設計をしていて。ひどく二度手間のように感じます。

しかも、Python では len の他にも abs, bool, str, repr, next, iter が、 メソッドを定義して組み込み関数 を呼び出すように定められています。

なぜ、メソッド呼び出しではなく、 無理やり関数呼び出しをするように設計されているのでしょうか?

>>> lst = [0, 1, 2, 3]
>>>
>>> # 関数 ... 実装されている。
>>> len(lst)
4
>>>
>>> # メソッド ... 実装されていない。
>>> lst.len()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'len'
>>> 

Pythonのオブジェクト指向っぽくないところ Pythonには関数がある。便利でよく使う関数(標準出力に文字を出力する print() 関数や、配列などの長さを求めるlen() 関数など)は 組み込みではじめから用意されている。関数は何かしらのオブジェクトに関連づけられたメソッドではないため、オブジェクト指向ではないところだ。

Guido のメール

Guido がそれについてメーリングリストの中で説明しているので、和訳したいと思います。
[Python-3000] Special methods and interface-based type system

特殊メソッドとインターフェースベースの型システム
Special methods and interface-based type system

んー、私はあなたの主張に(ワイの注釈: 特殊メソッドを __special__ ではなく special として定義するべきだという主張に) 同意できるかな..(ちょっと考えてみますね ^^。
Hm. I'm not sure I agree (figure that 😃.

2つのちょっとした Python の設計背景があります。まず、それについて説明しましょう。
There are two bits of "Python rationale" that I'd like to explain first.

まず第一に私は Human Computer Interaction, HCI の観点から x.len() よりも len(x) を選びました。 (obj.__len__() メソッドを定義して len(obj) 関数の動作を定義するのは、だいぶ後になってから実装されました。) 実際には2つの理由があります、共に HCI によるものです。
First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:

(a) いくつかの演算については、前置記法は後置記法よりも読みやすい ー 前置記法(そして中置記法!)の演算は、数学の中で長い伝統を持っている。 前置記法と中置記法の演算は、表記法に適していて、数学者が問題について考えやすくする。
(a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem.

x*(a+b) のような式を x*a + x*b に書き換える容易さと、生のオブジェクト指向の表記を使って同じことをする難しさを比べてみてください。
Compare the ease with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.

(b) 私が len(x) とコードに書かれているのを読んだときは、何かの長さを問い合わせているのだろうというのはわかります。 このことは2つのことを示しています。結果は整数であること、引数は何らかのコンテナのであること。 When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container.

反対に、x.len() を読んだときは、x がインターフェイスを実装しているか、 または標準的な len メソッドを持ったクラスから継承した何らかのコンテナであることを事前に知っておかなければならない。 To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len().

mapping を実装していないクラスが get, keys メソッドを持っていたとき、 またはファイルではない何がしかのクラスが write メソッドを持っていたときに、 私たちがよく戸惑うのを、同じように経験してみてください (どういう意味なんだろう... おそらく、継承さえしていないような場合は、個々のメソッドの意味を類推することが、より難しくなる、とうことでしょうか。)
Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.

私が説明すると約束した2つ目の Python の設計背景は、なぜ特殊メソッドの見た目を単純に special とはせずに __special__ したのかだ。
The second bit of Python rationale I promised to explain is the reason why I chose special methods to look __special__ and not merely special.

私は、多くのクラスがメソッドをオーバーライドするだろうと考えた。例えば、一般的なメソッド名(例えば __add__ や __getitem__)、 あまり一般的でないメソッド名(例えば pickle の __reduce__。これは、長いこと C 言語で一切サポートされていませんでした。) I was anticipating lots of operations that classes might want to override, some standard (e.g. __add__ or __getitem__), some not so standard (e.g. pickle‘s __reduce__ for a long time had no support in C code at all).

私はこれらの特殊なメソッドには、一般的なメソッド名を使って欲しくなかった。 なぜなら、すでに設計されたクラス、またはこれらの全ての特殊メソッドを覚えていないユーザによって書かれたクラスが、 意図せずメソッドをオーバーライドしてしやすく、結果として悲劇的な結果を引き起こす可能性を秘めているからだ ("すでに設計されたクラス" というのは、特殊メソッドを追加した時に、古いコードで同じ特殊メソッド名が既に使われてしまうと、 後方互換性が失われることを指しているのかな..)
I didn’t want these special operations to use ordinary method names, because then pre-existing classes, or classes written by users without an encyclopedic memory for all the special methods, would be liable to accidentally define operations they didn’t mean to implement, with possibly disastrous consequences.

メールの解説

疑問: どうしてメソッドよりも関数なの?

メソッドよりも関数が読みやすいから

[Python-3000] Special methods and interface-based type system

んー、私はあなたの主張に(特殊メソッドを __special__ ではなく special として定義するべきだという主張に) 同意できるかな..(ちょっと考えてみますね ^^。
Hm. I'm not sure I agree (figure that 😃.

2つのちょっとした Python の設計背景があります。まず、それについて説明しましょう。
There are two bits of "Python rationale" that I'd like to explain first.

まず第一に私は Human Computer Interaction, HCI の観点から x.len() よりも len(x) を選びました。 (obj.__len__() メソッドを定義して len(obj) 関数の動作を定義するのは、だいぶ後になってから実装されました。) 実際には2つの理由があります、共に HCI によるものです。
First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:

昔は len 関数の中に、各クラスに対するオブジェクトの長さを計測する処理が、まとめて定義されていました。 いまでは各クラスの __len__ メソッドの中に、それぞれ定義されています。

複数の型に対しての総称的な操作で、対象のオブジェクトがメソッドを全く持っていなかった (例えば、タプル) としても働くよう意図したものに関数は使われました。
Python にメソッドを使う機能と関数を使う機能があるのはなぜですか?

理由 1: 接頭辞は、接尾辞よりも読みやすいから。
理由 2: メソッドは、継承の有無を確認しないといけないから。

理由 1: 接頭辞は、接尾辞よりも読みやすいから。

正確には、接頭辞は接尾辞よりも読みやすいから。 この文章は、メソッド(後置記法)は、読みにくい。関数(前置記法)は、読みやすいと言っているのかな。 そうだとしたら、結構、恐ろしい文章。

[Python-3000] Special methods and interface-based type system
(a) いくつかの演算については、前置記法は後置記法よりも読みやすい ー 前置記法(そして中置記法!)の演算は、数学の中で長い伝統を持っている。 前置記法と中置記法の演算は、表記法に適していて、数学者が問題について考えやすくする。 (a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem.

x*(a+b) のような式を x*a + x*b に書き換える容易さと、生のオブジェクト指向の表記を使って同じことをする難しさを比べてみてください。
Compare the ease with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.

書き換えやすさについて検討。メソッドは、後置記法というよりも、中置記法っぽくなってしまっていますが。 ただ、どちらが書き換えやすいか、と言われると、たしかに関数の方が、書き換えやすい。それに関数の方が読みやすい。

from operator import add
from operator import mul


def sample_code():
    # 書き換えやすい
    x, a, b = 3, 4, 5
    assert mul(x, add(a, b)) == add(mul(x, a), mul(x, b))
    
    # 書き換えにくい
    x, a, b = map(Int, (x, a, b))
    assert x.mul(a.add(b)) == x.mul(a).add(x.mul(b))


class Int(int):
    def mul(self, other):
        return type(self)(self * other)
    
    def add(self, other):
        return type(self)(self + other)


sample_code()

理由 2: メソッドは、継承の有無を確認しないといけないから。

関数で呼び出す場合、組み込み関数として len が規定されていれば、 プログラムを読む側は len という関数名だけで、 それがオブジェクトの長さを返す関数だと判別できます。

# オブジェクトの長さが返ってくる。
len(obj)

反対に、メソッドで呼び出す場合、 オブジェクトの長さを返すメソッド len が抽象メソッドを持つ Len クラス が規定されていたとして規定されていたとしても、 それがオブジェクトの長さを返す関数だと判別できません。

# 何が返ってくるか、わからない。
obj.len()

するとある obj.len がメソッドが、抽象メソッドを len を実装したものなのか、 あるいは別の用途で実装されたメソッドなのか、 obj.len を見ただけでは判別がつかないからです。 結局、ちゃんと確認しようと思ったら obj.len メソッドのコードを読まないといけなくなります。

class Len:
    def len(self):
        """return length of object."""
        raise NotImplementedError

# Len を継承していなかった..
class C:
    def len(self):
        return 'Hello, world!'

obj = C()
obj.len()
# Hello, world!  <- 長さ int じゃなくて文字列 str が返ってきた!

[Python-3000] Special methods and interface-based type system
(b) 私が len(x) とコードに書かれているのを読んだときは、何かの長さを問い合わせているのだろうというのはわかります。 このことは2つのことを示しています。結果は整数であること、引数は何らかのコンテナのであること。 When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container.

反対に、x.len() を読んだときは、x がインターフェイスを実装しているか、 または標準的な len メソッドを持ったクラスから継承した何らかのコンテナであることを事前に知っておかなければならない。 To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len().

mapping を実装していないクラスが get, keys メソッドを持っていたとき、 またはファイルではない何がしかのクラスが write メソッドを持っていたときに、 私たちがよく戸惑うのを、同じように経験してみてください (どういう意味なんだろう... おそらく、継承さえしていないような場合は、個々のメソッドの意味を類推することが、より難しくなる、とうことでしょうか。)
Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.

こんなことし出したら組み込み関数だらけになってしまうんじゃ無いかなとも思ったのですが、 よく使うものについてだけ、組み込み関数として採用したという理解でいいのでしょうか。

確かに len(obj) と書かれているから、あーオブジェクトの数かと思ってさらっと流しています。 しかし、これがもし obj.len() だと、さらっと流せないかもしれない気がします。

疑問: なんで len メソッドじゃなくて
__len__ メソッドで定義するの?

答え: 一般的な語を使いたくないから。

len メソッドを定義して、len 関数で呼び出す。これでいいんじゃないの?って思うわけです。

class C(object):
    def len(self):
        return 1

obj = C()
len(obj)  # 1

しかし、クラスは継承されることを前提にしているので、メソッドに一般的な名前を使いたくなかったらしいです。

[Python-3000] Special methods and interface-based type system
私が説明すると約束した2つ目の Python の設計背景は、なぜ特殊メソッドの見た目を単純に special とはせずに __special__ したのかだ。
The second bit of Python rationale I promised to explain is the reason why I chose special methods to look __special__ and not merely special.

私は、多くのクラスがメソッドをオーバーライドするだろうと考えた。例えば、一般的なメソッド名(例えば __add__ や __getitem__)、 あまり一般的でないメソッド名(例えば pickle の __reduce__。これは、長いこと C 言語で一切サポートされていませんでした。)
I was anticipating lots of operations that classes might want to override, some standard (e.g. __add__ or __getitem__), some not so standard (e.g. pickle‘s __reduce__ for a long time had no support in C code at all).

私はこれらの特殊なメソッドには、一般的なメソッド名を使って欲しくなかった。 なぜなら、すでに設計されたクラス、またはこれらの全ての特殊メソッドを覚えていないユーザによって書かれたクラスが、 意図せずメソッドをオーバーライドしてしやすく、結果として悲劇的な結果を引き起こす可能性を秘めているからだ ("すでに設計されたクラス" というのは、特殊メソッドを追加した時に、古いコードで同じ特殊メソッド名が既に使われてしまうと、 後方互換性が失われることを指しているのかな..)
I didn’t want these special operations to use ordinary method names, because then pre-existing classes, or classes written by users without an encyclopedic memory for all the special methods, would be liable to accidentally define operations they didn’t mean to implement, with possibly disastrous consequences.

それに len っていうメソッドがあったら、わざわざ関数呼び出さないで、そのままメソッド使ってしまいそうですしね笑 __len__ メソッドにして len 関数を使ってもらうってのが、確かに良さそうですね。

◯ obj.next メソッドから obj.__next__ メソッドに

Guido は、このことをよく気にします。 イテレータでも Python 2 では obj.next メソッドを定義して next 関数で呼び出す方法から、Python 3 では len と同じように obj.__next__ メソッドを定義して, next(obj) から呼び出す方法に移行しています。

# Python 2
class Iterator(object):
    def next(self):
        ...
# Python 3
class Iterator(object):
    def __next__(self):
        ...

このように変更した理由は len と同じで next メソッドでは、イテレータの next なのかユーザが何か別の目的で作った next なのかわからないから。

この書き方を真似するべきか?

答え: たぶん違うと思います。

ディスパッチテーブルという言葉があります。簡単に抑えておいていただけると幸いです。
ディスパッチテーブル - 新人プログラマに知ってもらいたいメソッドを読みやすく維持するいくつかの原則 Qiita

型によって処理を切り替えることについて考えてみたいと思います。

1. 単一ディスパッチ - メソッドによる

一番簡単なのは、ダックタイピングを使ってしまうことです。 自分はこれしか使ったことがありません。

class ClsA:
  def opr(self):
    return 0

class ClsB:
  def opr(self):
    return 1

lst = [ClsA(), ClsB()]

for obj in lst:
    # ClsA, ClsB ともに opr で呼び出せる
    print(obj.opr())
... 
0
1
>>> 

2. 単一ディスパッチ - メソッドから関数による

len を真似て関数としてインターフェイスを定義すると読みやすくなると思います。 しかし、よほどプログラム全体を通して汎用的な処理でない限り、ないのではないかなと思います。

class ClsA:
  def _opr(self):
    return 0

class ClsB:
  def _opr(self):
    return 1

def opr(obj):
    return obj._opr()

lst = [ClsA(), ClsB()]

for obj in lst:
    # ClsA, ClsB ともに opr で呼び出せる
    print(opr(obj))
... 
0
1
>>> 

3. 単一ディスパッチ - 関数による

Python 3.4 で標準ライブラリ functools に singledispatch という関数が追加されました。 len 関数と同じような感覚でクラスごとに動作が異なる関数を定義できます。

# 対話モード >>> に
# コピペで実行できます。
from functools import singledispatch

class ClsA:
    pass

class ClsB:
    pass

@singledispatch
def opr(arg):
    raise NotImplementedError

@opr.register(ClsA)
def _(arg):
    return 0

@opr.register(ClsB)
def _(arg):
    return 1

lst = [ClsA(), ClsB()]

for obj in lst:
    print(opr(obj))
... 
0
1
>>> 

何が嬉しいんだって感じですが上で見た 1, 2 のような オブジェクト指向ライクの単一ディスパッチではなく、 関数型言語ライクな書き方で単一ディスパッチがしたかったらしいです。

4. 多重ディスパッチ - 関数による

Guido は、len とは別のやり方で、関数でも多態性、多重ディスパッチが実現できる方法を、ごく簡単ではありますが検討しています。 当時は、必要ではないという結論に達していたようです。 以下は Guido の昔のブログです。

Five-minute Multimethods in Python
I used to believe that multimethods were so advanced I would never need them. Well, maybe I still believe that, but here's a quick and dirty implementation of multimethods so you can see for yourself. Some assembly required; advanced functionality left as an exercise for the reader.

終わりに

計算機資源が潤沢になるにつれて、関数型言語が評価されるようになりました。 理解はできていないのですが、クラス、メソッドなんか不要なんやという言説を見た時は、目からウロコでした。

古いJavaのような、クラスにしかメソッドが所属できないモジュールシステムばかりの時代じゃありません。 クラスは基本的に不要だと思います
オブジェクト指向の呪いと、その避け方 - mizch's blog
アンチパターン: 特に理由もないクラスメソッドへの所属
ttps://mizchi.hatenablog.com/entry/2018/07/31/124354

メソッドよりも関数の方が読みやすい。関数で書けるのであれば、 オブジェクト指向である必要がないならば、関数で記述した方が望ましい気がします。 またよく使う処理については、組み込み関数として len を用意しておいた方が読みやすいと思います。

こういった洞察を持っているのが Guido の凄さだと思います。 関数は読みやすい、動的言語で関数でも多態性も実装したい、という2つの思いがあると、 len のような実装された方が導き出されるのかなと思います。

ただ、オブジェクト指向という枠の中で、組み上がってしまっているなかで、 例外的に関数を設けてしまったのは、どうしても一貫性を損ねる結果となってしまったかなと思います。 英語の文章、Guido のメールは昔の Python の Q&A からの引用になります。 いまは消されました。代わりにいまは次のような文章が掲載されています。

主な理由は歴史です(昔からそうやって実装されていたということ)。 ... 個々のケースについては粗探しのしようがありますが、 Python の一部であるし、根本的な変更をするには遅すぎます。 これらの関数は、大規模なコードの破壊を避けるために残す必要があります。

やはり、個人的には len が関数として定義されてしまったのは厳しいのではないかなと感じたりもします。 len, size, length とメソッド名がバラバラになる可能性はありますが、 コーディング規約レベルで PEP 8 のレベルで、統一しておくのがよかったのかなと思ったり、思わなかったりします。

よく len の処理について、辛辣に批評したものをよく目にします。 そして、悲しいことに、Guido が配慮したことの 十分の一も考えていないにも関わらず、 おそらく自分も気づかないうちによくやっているのだと思います。 現にいまもそういう記事を書いてしまい、お前が言うなよという話ではありますが。

ただ、いくらか気をつけないといけないなと感じたりもします。 Guido が BDFL から降りた時の文章を引用します。

いま PEP 572 の仕事は、終わった。私はこれ以上 PEP のために戦いたくないし、 多くの人が私が決定したことを侮蔑するのを聞きたくない。
Now that PEP 572 is done, I don't ever want to have to fight so hard for a PEP and find that so many people despise my decisions.
Transfer of power - Guido van Rossum