2013/01/30

Python の無名関数( lambda )の使い方

Python における無名関数の使い方についてご説明します。

Python では lambda 式を使って無名関数を定義することができます。

myfunc = lambda x: x ** 2 

myfunc(5)  # 25
myfunc(6)  # 36

lambda 式のフォーマットは lambda x: y です。 x が引数で、 y が戻り値です。

上の myfunc の場合

def myfunc(x):
    return x ** 2

と定義をしたのと同等の結果となります。

この myfunc 例だと無名関数を使うメリットはあまりありません。少し実践的なサンプルとして sorted()map()filter() とあわせて使う方法を見てみましょう。

例: sorted()

sorted() は、与えられたリストをソートしてくれる関数です。与えられたリストそのものは変更せずに、ソート済みのコピーを返してくれます。

たとえば、

l1 = [(7, 2), (3, 4), (5, 5), (10, 3)]

というリストがあったとして、このリストの要素(タプル)のふたつめの要素でソートしたい場合は、次のように書きます。

l2 = sorted(l1, key=lambda x: x[1])

結果は次のようになります。
print(l2)  # [(7, 2), (10, 3), (3, 4), (5, 5)]

例: map()

次に、 map() と組み合わせる例を見てみます。 map() は、リストやタプルの各要素に対して同じ処理を施して、同じ長さのリストにそのすべての結果を格納して返してくれる関数です。 map(関数, リスト) という形で使います。
l1 = [1, 3, 5]

l2 = map(lambda x: x ** 2, l1)

print(l2)  # [1, 9, 25]

このようにすると、各要素を二乗したものをリストとして得ることができます。ちなみにこれはリスト内包で次のように書いても同じ結果が得られます。
l2 = [x ** 2 for x in l1]

例: filter()

最後に、 filter() と組み合わせる例を見てみます。 filter() は、与えられたリストから条件に合うもののみを抽出してリストにしてくれる関数です。

たとえば、次のようなクラスと、そのインスタンスを並べたリストがあるとします。
class Album(object):
    def __init__(self, title, artist):
        self.title = title
        self.artist = artist
a1 = Album("A Hard Day's Night",
           'The Beatles')
a2 = Album('The Rolling Stones', 
           'The Rolling Stones')
a3 = Album("Abbey Road", 
           'The Beatles')

albums = [a1, a2, a3]

このリスト albums の中からアトリビュート artist が「 The Beatles 」のもののみを抽出したい場合は、次のように書けば OK です。
albums_beatles = filter(lambda album: album.artist == 'The Beatles', albums)

結果は次のように、条件にあったものだけのリストとなるはずです。
for a in albums_beatles:
    print a.artist, '-', a.title
# The Beatles - A Hard Day's Night
# The Beatles - Abbey Road

以上です。

2013/01/24

Pythonのクラスの使い方

Pythonのクラスの使い方をご紹介します。

定義

クラスは「class [クラス名](継承したいクラス名):」という形で定義します。
class MyClass(ParentClass):
    """Myclass for ...
    """

    def __init__(self, name, x, y):
        self.name = name
        self.x = x
        self.y = y

    def getX(self):
        return self.x
この例でいうと
  • MyClass クラス名
  • ParentClass 継承したいクラス名
  • x アトリビュート
  • y アトリビュート
  • __init__ メソッド
  • getX メソッド
となります。

派生クラス、基底クラスということばを使うなら、MyClassが派生クラス、ParentClassが基底クラス、にあたります。ちなみに、ParentClassをこのように継承する場合は、MyClassの定義よりも前(上)の部分でParentClassを定義しておく必要があります。

基底クラスを指定しない場合は、()(かっこ)の中身に何も書かず「class MyClass()」とするか、「Object」という基本クラスを入れて「class MyClass(Object)」とします。

「def~」の部分はメソッドの定義です。インスタンスメソッドの第一引数は必ずself(そのインスタンス自身)を入れることになっています。

ここで定義されているふたつのメソッドのうち、getXは通常のメソッドですが、__init__ は元からその用途が決められている特殊メソッドです。__init__の場合はコンストラクタのふるまいを指定するメソッドになります。

インスタンスの生成

上の例のように__init__を定義した場合、インスタンスmc1は次のように生成します。
mc1 = MyClass('Voyager', 10, 5)

__init__の定義文に書かれている引数のうち、self以外の引数をすべて与えてあげます。この場合では
  • mc1.name に 'Voyager'
  • mc1.x に 10
  • mc1.y に 5
が格納されます。

「__init__」のほかにも、「__str__」、「__le__」などの特殊メソッドが数多く用意されており、公式ドキュメントの特殊メソッドについて説明したパートにまとめて紹介されています。

私はほとんど使ったことがないので馴染みがないのですが、インスタンスメソッドではなく「クラスメソッド」を定義したい場合は次のように書けばよいようです。
@classmethod
def f(cls, arg1, arg2, ...):
    ...
クラスメソッドに関する公式ドキュメントはこちらにあります。

最後に、「class MyClass(ParentClass):」の一行下にある「"""My Class for ...    """」という部分は、クラスの説明文を書くところです。一般に「docstring」と呼ばれ、「[クラス名].__docs__」に格納されます。今回の場合だと
print MyClass.__docs__
とすると、「My Class for ~」という文字列が表示されます。docstringについて詳しくは、PEP 257で解説されていますのでよろしければそちらをご覧ください。

2013/01/22

Python Tips:dict(辞書)型の中身をソートしたい

Pythonのdict型のオブジェクトをキーやバリューでソートしてから取り出す方法についてご紹介します。

シンプルでかんたんなのは sorted() 関数に key オプションを渡す方法です。

次のような辞書dに対して
d = {'Tokyo': 10,
     'Osaka': 3,
     'Hokkaido': 12}
sorted() 関数にソートのキーを指定するための無名関数を渡します。

キーでソートするなら
sorted(d.items(), key=lambda x: x[0])
# => [('Hokkaido', 12), ('Osaka', 3), ('Tokyo', 10)]

バリューでソートするなら
sorted(d.items(), key=lambda x: x[1])
# => [('Osaka', 3), ('Tokyo', 10), ('Hokkaido', 12)]
となります。

operatorライブラリのitemgetter(0)というメソッドを使えば
from operator import itemgetter
sorted(d.items(), key=itemgetter(0))
# => キーでソートした結果
と書くことも可能です。


参考
Sorting HOW TO — Python公式ドキュメント
HowTo/Sorting - Python Wiki
python - How to sort (list/tuple) of lists/tuples? - Stack Overflow

2013/01/21

Pythonの関数の使い方

Pythonの関数の使い方をご紹介します。

定義

関数はdefで定義します。
def printhello(string):
    print 'hello, %s' % string

「def [関数の名前](引数):」という一行を書いて、関数の中身はインデントを下げて書いていきます。def文の末尾の:(コロン)は必須です。

使い方

printhello('world')  # 'hello, world'
定義文の後に引数を与えて使います。定義文よりも前に使うことはできません。

他のファイルの中で定義された関数は、import文で読み込んでから使います。たとえば、「myhelper.py」というPythonコードの中で定義されたmyfunc1という関数を使いたい場合は
from myhelper import myfunc1 

myfunc1(x)
と書くことで使うことができます。構文は「from [ファイル名] import [関数名]」です。

他のコードの中で定義された関数をまとめてimportしたい場合は
from [ファイル名] import *
とすることで一括でimportできます。ただ、このように何をimportするのかを明示しない場合には名前が衝突してしまう可能性もあるので注意が必要です。

ファイル全体をimportする場合には、fromは使わず、importの対象に直接ファイル名を指定する次のような使い方も可能です。
import myhelper

myhelper.myfunc1(x)

引数

引数はさまざまな形で与えることができます。

def sumtotal(x, y, z):
    return x + y + z
と関数sumtotalを定義すると
sumtotal(1, 2, 3)  # 6が返される
sumtotal(x=1, y=2, z=3)  # 同じく6が返される
sumtotal(1, 2, z=3)  # 同じく6が返される
という風に、さまざまなスタイルで呼び出すことができます。単純に変数を与えるだけで使うこともできますし、引数の名前(「キーワード」)を指定して使うこともできます。

ただし、引数の名前を指定したあとに名前を指定せずに引数を入れることはできません。どういうことかというと
sumtotal(x=1, y=2, 3)  # エラー
とすると、x,yをキーワードで指定した後にzについては指定していないので、この場合はエラーとなります。

ちなみに、最初の関数printhelloのように、return文を書かなかった場合のデフォルトの戻り値は「None」となります。
print printhello('world')
# hello, world
# None
# と出力される

オブジェクトとしての関数

Pythonの関数の特徴のひとつは、「関数自体がオブジェクト」という点です。関数そのものを変数のように扱うことができます。

たとえば、sin、cos、tanという3つの関数を定義した後で、
trgs = [sin, cos, tan]
trgs[0](1)  #  sin(1)の値が返される
trgs[1](1)  #  cos(1)の値が返される
trgs[2](1)  #  tan(1)の値が返される
といった使い方ができます。

この特徴を使うと、たとえば「flag」という変数が
  • 0 なら sin(x) を
  • 1 なら cos(x) を
  • 2 なら tan(x) を
返したいような場合に、if文を使わなくても、trgsというリストを定義して
trgs = [sin, cos, tan]
trgs[flag](x)
というように、シンプルな書き方をすることができます。

2013/01/14

Python の文字列演算

Pythonの文字列型に関する基本的な演算についてご紹介します。

連結

「+」は文字列の連結、「*」は文字列の繰り返して連結となります。
s1 = 'hello'
s2 = 'world'
としたとき、
s1 + s2  # 'helloworld'
s1 * 3  # 'hellohellohello'
となります。

比較

数値型と同様に、文字列型でも比較演算(== != < >など)を行うことができます。
s1 == s2  # False
s1 != s2  # True
s1 < s2  # True

特定の文字が含まれているかどうかのチェック

文字列中に特定の文字や文字列が含まれているかどうかのチェックはin演算子で行うことができます。
'h' in 'hello'  # True
'hel' in 'hello'  # True

インデックス・スライス

文字列の一部を取り出す処理――インデックスやスライスは[](大かっこ)で行うことができます。インデックスは1始まりではなく0始まりです。
s1[0]  # h
s1[1]  # e
s1[2]  # l

マイナスの数値を指定すると、文字列の後ろ側から順に取り出すことができます。-1が一番後ろの文字です。
s1[-1]  # o
s1[-2]  # l
s1[-3]  # l
s1[-4]  # e
s1[-5]  # h

スライス(サブストリング取り出し)は、[](大かっこ)を使ってs1[begin:end]という形で行うことができます。
s1[1:4]  # ell
s2[0:4]  # worl
s1[begin:end]とすると、s1[begin]で始まり、ちょうど「end-beginコ」の文字を抜き出すことになります。

スライスにおいても、マイナスのインデックスを使うことができます。
s1[1:-1]  # ell
s2[0:-2]  # wor

文字列の長さを越えたインデックスを指定するとエラーがあがりますが、スライスにおいて文字列の長さを越えたインデックスを指定してもエラーは出ません。
s1[100]  # エラー
s1[100:105]  # 空の文字列が返される ''

また、スライスの始まりと終わりのインデックスは省略することが可能です。省略した場合、beginは0を、endはlen(s1)を入力した場合と同じ結果が返ってきます。
s1[:-1]  # hell
s2[1:]  # orld

s1[begin:end:skip]とすると、何個か飛ばしにスライスすることも可能です。
s2[0:5:2]  # wrd

文字列そのものの評価

文字列をif文で評価すると、文字列が空の場合のみFalseを、それ以外はTrueを返します。
if 'hello':
    print 'A'
else:
    print 'B'
# 'A'
if '':
    print 'A'
else:
    print 'B'
# 'B'

その他のよく使う文字列関連の関数・メソッド

他にも、文字列に対して使う関数やメソッドが豊富に用意されています。

文字列の長さはlen()関数で取得できます。
len(s1)  # 文字列の長さ 5

s1.count(s2)  # s1中に文字列s2が現れる回数
s1.encode(encoding)  # s1を指定された文字コードに変換
s1.find(s2)  # s1の中に文字列s2があればその最初のインデックス
s1.rfind(s2)  # s1の中に文字列s2があればその最後のインデックス
s1.index(s2)  # s1の中に文字列s2があればその最初のインデックス
find()とindex()のちがいは、文字列s2がなかったときの挙動です。find()は文字列s2がなかったときは-1を返しますが、index()はValueErrorというエラーを返します。

文字列を分割するにはsplit()かpartition()を使います。
s1.split(s2)  # s1を文字列s2で分割したリスト
s1.partition(s2)  # s1を文字列s2で分割したリスト
split()とpartition()のちがいは、split()が返すリストの要素にs2を含まないのに対して、partition()がs2を含む点です。

公式のドキュメントにはその他数多くのメソッドの使い方が載っています。
String Method - Python v2.7.3 documentation

2013/01/07

Pythonの数値演算

Pythonの数値型の基本的な演算(算術演算)についてご紹介します。

最も基本的な四則演算――加減乗除(+ - * /)は次のように使うことができます。

a = 10
b = 3
としたとき、加減乗除は次の形で行うことができます。

a + b  # 13

a - b  # 7

a * b  # 30

a / b  # 3
a % b  # 1

除算は、「/」で商、「%」で余りを計算することができます。

また、a、bともに整数型(int)の場合の挙動は、Pythonのバージョンによって異なるため注意が必要です。Python 2.*系では結果は整数型(10/3 = 3)ですが、Python 3.*系では結果は不動小数点型(10/3 = 3.333...)となります。

ちなみに、a、bの符号が異なる場合の結果はは次のとおりになります。負の数を扱う場合はこの仕様を認識した上で使うのがよいかと思います(Python 2.*系の場合です)。
-10 / 3  # -4
-10 % 3  # 2

指数

指数の演算も次のとおり行うことができます。
2**3  # 8

比較

比較演算子(== != <> < <= > >=)も、他の言語と同様にひととおり使うことができます。

加減乗除と同じく
a = 10
b = 3
としたとき
a == b  # False
a != b  # True
a < b  # False
a > b  # True
となります。

モジュール

また、「math」という標準モジュールを使うと、その他の頻出演算や定数を使うことができます。
import math

math.sin(1)  # サイン
math.cos(1)  # コサイン
math.tan(1)  # タンジェント
math.atan(1)  # アークタンジェント
import math
math.pow(2,3)  # 指数の演算 8.0 
math.fabs(-3)  # 絶対値 3.0
import math
math.pi  # 3.141592...
math.e  # 2.718...

複素数

複素数の演算については、複素数型のメソッド、または「cmath」というモジュールで行うことが可能です。
c = 3 + 4j
c.real  # 3.0
c.imag  # 4.0
import cmath
cmath.phase(c)  # 角度を返す
cmath.polar(c)  # (ベクトルの大きさr, 角度phi)を返す (5.0, 0.927...)

2013/01/04

Pythonにまつわるアイデア:PEP 8

PEP 8 」とは「 Style Guide for Python Code 」ーー Python コードの「書き方ガイド」です。

コードは一般に「書かれる時間」よりも「読まれる時間」の方が長いという事実に基づいて、「スタイルを統一し読みやすいコードを書こう」というアイデアのもとに作られたのがこのガイドです。

レイアウトなどの大きな視点のお話から空白やコメントの使い方といった細かなポイントまで、「こういうときにはこう書こう」という規約が数多く提案されています。

ボリュームが多いのでここではその一部だけをご紹介したいと思います。詳細を確認したい場合はぜひ原文をご確認ください。他の言語で書くときにも参考になる規約です。

まずはレイアウトまわりのポイントから。


レイアウト

インデントは「スペース4つ」で統一すること。

OK
for e in li:
    print e  # スペース4つ

NG
for e in li:
  print e  # スペース2つ

文の途中で改行する場合は、括弧の直後で縦のラインをあわせること。

OK
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

文の途中で改行する場合、空白行をはさまず直後に次の文がくる場合は、区切りがわかりやすいよう、改行後のインデントを落とすこと。

OK
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

一行の最大文字数は79文字とすること。

行が長くなる場合は、 () をうまく使って改行すること。できれば\(バックスラッシュ)ではなく () を使うこと。

演算子のところで改行する場合は、演算子の前ではなく「後」で改行すること。

OK
y = a + b + c + \
    d + e + f + g

NG
y = a + b + c \
    + d + e + f + g

トップレベルの関数やクラスの定義ブロックの前後には2行空行を入れること。

OK
class A(object):
    # contents of A


class B(object):
    # contents of B

クラスの中のメソッド定義の前後には1行空行を入れること。

その他、ロジカルな塊を区別するために空行を使うこと。

文字エンコードには、「ASCII」か「Latin-1エンコーディング」(ISO-8859-1)を用いること。
PEP0263

Python 3.0以降のバージョンでは、utf-8を用いること。
PEP 3120

import文は原則1行にまとめず、モジュールごとに分けて書くこと。

OK
import os
import sys

NG
import sys, os

ただし、クラス名などをまとめてimportするのはOK。

OK
from subprocess import Popen, PIPE

import文はコードの一番最初に書くこと。

モジュールをimportする順番は、おおよそ次のじゅんばんで 行うこと。
  1. 標準ライブラリ
  2. サードパーティライブラリ
  3. ローカルライブラリ

半角スペース

各種かっこ(() [] {})の中の両端ではスペースを空けないこと。

OK
spam(ham[1], {eggs: 2})

NG
spam( ham[ 1 ], { eggs: 2 } )

コンマ、コロン、セミコロンの直前ではスペースを空けないこと。

OK
a, b = c, d;
{"key": "value"}

NG
a , b = c , d ;
{"key" : "value"}

()(丸かっこ)や[](大かっこ)の直前にはスペースを空けないこと。

OK
spam(1)
dict['key'] = list[index]

NG
spam (1)
dict ['key'] = list [index]

縦のラインをあわせるための代入(=)の前後での連続スペースは用いないこと。

OK
x = 1
y = 2
long_variable = 3

NG
x             = 1
y             = 2
long_variable = 3

各種演算子(+ - * / == in not is)の前後にはスペースをひとつ入れること。

OK
i = i + 1
submitted += 1

NG
x = x*2-1

hypot2 = x*x + y*y
c = (a+b) * (a-b)

ただし、関数のキーワード引数の場合の = には前後にスペースを入れないこと。

OK
def complex(real, imag=0.0):
    return magic(r=real, i=imag)

「 ; 」を使えば複数の文を1行に入れることができるがそれは使わないこと。


コメント

コメントを最新に保つこと。

コメントが文である場合は、最初の文字は大文字で始めること。

英語圏以外の人も、そのコードが同じ言語圏の人にしか読まれないと120%言い切れる場合を除き、コメントは英語で書くよう努めること。

publicなモジュールや関数には必ずdocstringをつけること。

バージョン管理

OK
__version__ = "$Revision: 16dd63848921 $"
# $Source$


変数名のつけ方

さまざまな変数名のスタイルをしっかりと使い分けること。
  • 小文字(lowercase)
  • 大文字(UPPERCASE)
  • アンダースコアつき小文字(lower_case_with_underscores)
  • アンダースコアつき大文字(UPPER_CASE_WITH_UNDERSCORES)
  • 大文字始まり(CapitalizedWords)
  • 2つめの単語以降大文字始まり(mixedCase)

_ 始まりなどの変数名には特殊な意味があることを認識して使うこと。

モジュール名は原則すべて小文字(lowercase)で。可読性を高めるために _ も使ってよい。

クラス名は大文字始まり(CapitalizedWords)で。

関数名は、原則すべて小文字(lowercase)で。可読性を高めるために_も使ってよい。

メソッドの1番目の引数は、インスタンスメソッドの場合は「self」、クラスメソッドの場合は「cls」を使うこと。

定数は、アンダースコアつき大文字(UPPER_CASE_WITH_UNDERSCORES)で。

その他

例外処理の try 文の中身は、できるかぎり小さいまとまりにすること。

OK
try:
    value = collection[key]
except KeyError:
    return key_not_found(key)
else:
    return handle_value(value)

NG
try:
    # Too broad!
    return handle_value(collection[key])
except KeyError:
    # Will also catch KeyError raised by handle_value()
    return key_not_found(key)

例外処理の except 文では例外の種類をできるかぎり明示すること。

OK
try:
    import platform_specific_module
except ImportError:
    platform_specific_module = None

NG
try:
    import platform_specific_module
except:
    platform_specific_module = None

シーケンス(文字列・リスト・タプル)が空かどうかを判定するときは、空シーケンスは False となる事実を使ってシンプルに書くこと。

OK
if not seq:

NG
if len(seq)


・・・以上です。

コードの書き方やスタイルではなく、プログラムのより本質的な部分である「アルゴリズム」や「ロジック」に集中するためには、このようなあらかじめまとめられたルールを踏襲するのがよいかと思います。ただし、それも場合によりけりで、たとえば次のようなケースでは「このルールをムリに適用しない方がよいかもね」と PEP 8 の中でも言及されています。

  • ルールを適用するとかえって読みづらくなる場合
  • 既存のコードがこのルールに従っていない場合

繰り返しになりますが、ここにあるのがすべてではないので(また、正確でなかったり間違っていたりもするかもしれないため)、詳細の確認は原文にあたっていただければと思います。


参考
- PEP 8 Style Guide for Python Code

2013/01/03

Pythonにまつわるアイデア:PEP 20

PEP 20」とは、別名「The Zen of Python」(禅・オブ・パイソン)。Pythonそのものの設計における基本的な考え方を表したアフォリズム集です。

Pythonコードの特徴である「シンプルさ」や「読みやすさ」の源泉となった考え方が、合計19コのことばとしてまとめられています。
  1. Beautiful is better than ugly.
  2. Explicit is better than implicit.
  3. Simple is better than complex.
  4. Complex is better than complicated.
  5. Flat is better than nested.
  6. Sparse is better than dense.
  7. Readability counts.
  8. Special cases aren't special enough to break the rules.
  9. Although practicality beats purity.
  10. Errors should never pass silently.
  11. Unless explicitly silenced.
  12. In the face of ambiguity, refuse the temptation to guess.
  13. There should be one-- and preferably only one --obvious way to do it.
  14. Although that way may not be obvious at first unless you're Dutch.
  15. Now is better than never.
  16. Although never is often better than *right* now.
  17. If the implementation is hard to explain, it's a bad idea.
  18. If the implementation is easy to explain, it may be a good idea.
  19. Namespaces are one honking great idea -- let's do more of those!

以下、日本語訳付きで順にご紹介します。原文のシンプルさとわかりやすさをなるべく再現する日本語訳を目指して書いてみました。

01

Beautiful is better than ugly.
「醜い」よりも「美しい」

02

Explicit is better than implicit.
「暗黙」よりも「明示」

03

Simple is better than complex.
「複雑」よりも「シンプル」

04

Complex is better than complicated.
でも、「複雑」でも「わかりづらい」よりはまし

* 03からつながっています

05

Flat is better than nested.
「ネスト」(入れ子状)よりも「フラット」

06

Sparse is better than dense.
「密集」よりも「ガラガラ」

07

Readability counts.
読みやすさってのは大事

08

Special cases aren't special enough to break the rules.
ルールを破ってまで作るべき特例なんてない

09

Although practicality beats purity.
「実用性」は「ピュアさ」(一貫性)に勝る、というのはそうなんだけど

* 09からつながっています

10

Errors should never pass silently.
エラーが起こっているのにそれがわからないなんてのは×

11

Unless explicitly silenced.
「そのエラーは通知しなくてもいいよ」と明示的に指定されたのなら話は別だけど

* 10からつながっています

12

In the face of ambiguity, refuse the temptation to guess.
「あいまいなもの」に出会ったら、「推測」で済ませたくなる誘惑には負けないで

13

There should be one-- and preferably only one --obvious way to do it.
何かをやるには、ストレートなやり方がひとつ、たったひとつだけあるはず

14

Although that way may not be obvious at first unless you're Dutch.
その方法は一目ではわかりにくいものかもしれないけど
(あなたがオランダ人というのなら、話は別かもね)

* 13からつながっています
* 「オランダ人」というのは、Pythonの原作者Guido van Rossumがオランダ人だからのようです


15

Now is better than never.
「やらない」よりも「今やる」

16

Although never is often better than *right* now.
「やらない」が「今すぐやる」よりいいこともよくあるけれど

* 15からつながっています

17

If the implementation is hard to explain, it's a bad idea.
説明が難しいのなら、その実装は良くないということ

18

If the implementation is easy to explain, it may be a good idea.
説明がカンタンなら、その実装は良いのかも

19

Namespaces are one honking great idea -- let's do more of those!
名前空間ってのは、すんげーアイデアなんだなぁ。これ、もっと使っていこうよ!

・・・以上です。


ちなみに、PythonのIDLE(対話型インタフェース)から
import this
と打つと、このPEP 20がずらずらーっと表示されるようなイースターエッグもあります。


参考
PEP 20 The Zen of Python