1. ホーム
  2. python

[解決済み] 「許しを請うのではなく、許しを請う」 - 説明

2023-05-08 16:13:09

質問

この哲学について、個人的な意見ではなく、もう少し技術的なことをお聞きしたいのですが。

このフレーズは、あなたのコードが "pythonic" であるかどうかを確認するためのいくつかのリトマス テストの 1 つであることを理解しています。 しかし、私にとって、pythonic とは、クリーンで、シンプルで、直感的で、悪いコーディングのための例外ハンドラを搭載していないことを意味します。

では、実際の例です。 私はクラスを定義します。

class foo(object):
    bar = None

    def __init__(self):
        # a million lines of code
        self.bar = "Spike is my favorite vampire."
        # a million more lines of code

さて、手続き的な背景から、別の関数でこんなことをやってみたいと思います。

if foo.bar:
    # do stuff

焦っていると属性例外が発生し はしませんでした。 を実行すると属性例外が発生します。 つまり、quot;ask forgiveness not permission"は、私が代わりにこれを行うべきであると示唆しているのですか?

try:
    if foo.bar:
        # do stuff
except:
    # this runs because my other code was sloppy?

なぜtryブロックにロジックを追加した方が良いかというと、クラス定義に より曖昧にするため ? なぜ、最初にすべてを定義しないのか、つまり、明示的に 許可を与える ?

(try/exceptブロックの使用について、私を責めないでください...。私はどこでも使っています。 ただ、私が徹底的なプログラマーでなかったから、自分のエラーをキャッチするためにそれらを使うのは正しいとは思いません)。

それとも...私は「許しを請う」というマントラを完全に誤解しているのでしょうか?

どのように解決するのですか?

古典的な例として、quot;ask forgiveness not permission" から値にアクセスすることが挙げられます。 dict から値にアクセスすることです。 例えば

names = { 'joe': 'Joe Nathan', 'jo': 'Jo Mama', 'joy': 'Joy Full' }
name = 'hikaru'

try:
    print names[name]
except KeyError:
    print "Sorry, don't know this '{}' person".format(name)

ここで、発生しうる例外( KeyError ) を記述することで、起こりうるすべてのエラーに対して許しを求めるのではなく、自然に起こるであろうエラーに対してのみ許しを求めるようにしています。 比較のために、"ask permission first"のアプローチは次のようになります。

if name in names:
    print names[name]
else:
    print "Sorry, don't know this '{}' person".format(name)

または

real_name = names.get(name, None)
if real_name:
    print real_name
else:
    print "Sorry, don't know this '{}' person".format(name)

このようなquot;ask forgiveness"の例は、しばしば単純すぎることがあります。IMO では、次のことが明確ではありません。 try / except ブロックは、本質的に if / else . 本当の価値は、様々な方法で失敗する可能性のある操作--例えば構文解析など--を実行するときに、より明確になります。 eval() の使用、オペレーティング システム、ミドルウェア、データベース、またはネットワーク リソースへのアクセス、または複雑な数学の実行などです。複数の潜在的な障害モードがある場合、許しを得るための準備は非常に価値があります。

コード例に関するその他の注意点。

を杓子で使う必要はありません。 try / except のようなブロックが、変数の使用ごとに表示されます。それは恐ろしいことです。また self.bar の中に __init__() で設定されているので class の定義で設定されているからです。通常は、クラスで定義するか (クラスのすべてのインスタンスで共有されるデータである場合)、あるいは __init__() (で定義するのが一般的です(インスタンスデータで、各インスタンスに固有の場合)。

の値は None は未定義でもなければ、エラーでもありません。それは具体的で正当な値であり、none、nil、null、または nothing を意味します。多くの言語では、プログラマがオーバーロードしないように、このような値を持っています。 0 , -1 , '' (空文字列)などの便利な値があります。