3
months = ['January',
          'February',
          'March',
          'April',
          'May',
          'June',
          'July',
          'August',
          'September',
          'October',
          'November',
          'December']

def valid_month(month):
    if month:
        cap_month = month.capitalize()
        if cap_month in months:
            return cap_month

上記は、月のリストを作成し、基本的に、有効な月であるかどうかにかかわらず、ユーザーが入力した内容を出力する Python コードです。上記のコードはいいです。

以下は上記に似た別のバージョンですが、より使いやすいと思います。しかし、これがどのように機能するのか正確にはわかりません。この方法でpython辞書を見たことがないので、誰かがこのコードを調べて説明してくれます。ありがとうございます。

months_abbvs = dict((m[:3].lower(), m) for m in months)

def valid_month(month):
    if month:
        short_month = month[:3].lower()
        return month_abbvs.get(short_month)
4

3 に答える 3

5

その余分なステップから得られるものを印刷すると役立つ場合があります。

>>> months_abbvs
{'apr': 'April',
 'aug': 'August',
 'dec': 'December',
 'feb': 'February',
 'jan': 'January',
 'jul': 'July',
 'jun': 'June',
 'mar': 'March',
 'may': 'May',
 'nov': 'November',
 'oct': 'October',
 'sep': 'September'}

したがって、小文字の略語から完全な月名へのマッピングがあります。

それはどのように機能しますか?まず、式が何をするかを見てみましょう。

>>> m = 'December'
>>> m[:3].lower()
'dec'
>>> m[:3].lower(), m
('dec', 'December')

したがって、内包表記は毎月それを行います。

>>> [(m[:3].lower(), m) for m in months]
[('jan', 'January'),
 ('feb', 'February'),
 ('mar', 'March'),
 ('apr', 'April'),
 ('may', 'May'),
 ('jun', 'June'),
 ('jul', 'July'),
 ('aug', 'August'),
 ('sep', 'September'),
 ('oct', 'October'),
 ('nov', 'November'),
 ('dec', 'December')]

チュートリアルで詳しく説明されているように、内包表記は基本的にループの省略形です。特に、これは:

>>> m2 = [<expression with m> for m in months]

…は次と同等です:

>>> m2 = []
>>> for m in months:
...     m2.append(<expression with m>)

リスト内包表記の代わりにジェネレータ式を使用すると、シーケンスがリストではなく遅延イテレータとして構築されることになります。

そして、結果を (いずれかの方法で) に渡すと、dict各タプルの最初の値を 2 番目の値にマッピングする辞書が作成されます。


辞書内包表記として、これをもう少し読みやすく書くことができます。

months_abbvs = {m[:3].lower(): m for m in months}

m[:3].lower()さらに良いことに、繰り返し書くのではなく、適切な名前を付けて、次のように使用します。

def abbreviate(m):
    return m[:3].lower()
months_abbvs = {abbreviate(m): m for m in months}

その後:

def valid_month(month):
    if month:
        short_month = abbreviate(month)
        return month_abbvs.get(short_month)

ここで、新しいバージョンで入力を使用して行うことは次のとおりです。

short_month = month[:3].lower()
return month_abbvs.get(short_month)

month_abbvsは であるため(dict出力するか、何かを呼び出すことによって作成されたという事実からdictわかります)、getメソッドはdict.getです。したがって、リンクされたドキュメントで説明されているように、month_abbvs.get(short_month)は と同じmonths_abbvs[short_month]ですが、キーshort_monthが見つからない場合None、例外を発生させる代わりに を取得します。

したがって、 が指定された場合'October'、 に設定さshort_month'oct'ます。そして、それを略語辞書で調べると、 が返されます'October''OCT'または'october'またはを指定'octal digit string'すると、同じものも返されます。空でない文字列はすべて真であるため、次のようなことを行った場合if valid_month('October'):、真になります。

しかし、与えられた場合、たとえば、'Muhammed'に設定さshort_month'muh'ます。そして、あなたはそれを調べますが、そこにはありません。上記で説明したように、このgetメソッドはNone不明なキーに対して返されるため、 を返しNoneます。Noneは偽なので、 のようなif valid_month('Muhammed'):ことをした場合、真ではなくなります。

言い換えれば、それは関数をより寛大にします — これは改善かもしれませんし、悪いことかもしれません (あるいは両方の少しかもしれません'OCT'— 働きたかったのにそうでなかったかもしれません'octal digit string')。

于 2013-09-05T19:44:31.637 に答える
2
months_abbvs = dict((m[:3].lower(), m) for m in months)
# months_abbvs = { 'jan':'January', 'feb':'February',... }
# the actual operation is two-step:
#     1. [(m[:3].lower(),m) for m in months] list comprehension over the "months" list which:
#     1.1. [m[:3].lower()] take first three letters of each item in the list, apply lowercase()
#     1.2. [(m[:3].lower,m)] return a tuple of (1.1, item)
#     2. [dict(...)] build a dictionary from the list comprehension
#     2.2. for each tuple returned from (1.2), create a key:value pair in the dict

def valid_month(month):
    if month:
        short_month = month[:3].lower()
        # get first three letters as lowercase string
        return month_abbvs.get(short_month)
        # 1. [month_abbvs.get(short_month)] perform dict.get(key)
        # 2. return result of 1 (None if no such key exists)

これがより効率的である理由はdict、内部表現にハッシュセットを使用するため、キーが存在するかどうかを見つけることは (償却された) O(1) 操作ですが、リストに対して同じことを行うことは最悪のケースです。サイズ n のリストに対するシナリオ O(n) 操作。

@abarnert のコメントによると、これにより、dict.get(key)コード内の反復ロジックを気にせずに a を実行するだけで済むため、コードがよりユーザーフレンドリーになります。条件は、「このセットのいずれかのケースに当てはまる [...]?」ではなく、「True/False」の質問になります。

于 2013-09-05T19:43:47.457 に答える