たまにはブログを書く

やる夫と Python で学ぶ Twitter の OAuth - YoshioriのBlog

よいまとめ!


はてブコメントより引用

id:agricola Python, あれげ リスト内包の使い方に美がないなぁ……。辞書のキーと値を、キーで並べ替えて取り出して=で連結するなら

['='.join((k, v)) for k, v in sorted(d.items(), key = lambda x: x[0])]

とか書く気がする。

そんな餌で俺様が釣られクマーーーーーーっ

>>> ['='.join((k, v)) for k, v in sorted(d.items(), key = lambda x: x[0])]
['a=k', 'b=j', 'c=i', 'd=h', 'e=g', 'f=f', 'g=e', 'h=d', 'i=c', 'j=b']

ふむ。なんだこのゴテゴテといらないものがくっついたコードは。

>>> ['='.join((k, d[k])) for k in sorted(d)]
['a=k', 'b=j', 'c=i', 'd=h', 'e=g', 'f=f', 'g=e', 'h=d', 'i=c', 'j=b']

>>> ['%s=%s' % (k, d[k]) for k in sorted(d)]
['a=k', 'b=j', 'c=i', 'd=h', 'e=g', 'f=f', 'g=e', 'h=d', 'i=c', 'j=b']

>>> ['%s=%s' % p for p in sorted(d.items())]
['a=k', 'b=j', 'c=i', 'd=h', 'e=g', 'f=f', 'g=e', 'h=d', 'i=c', 'j=b']

どれでもOK。僕なら2番目で書くかな。挙動は100%イコールというわけではなくて、"%s=%s"の方は辞書の値がstrでなくてもエラーにならない。


でもまあ、OAuthをコード付きで解説することがみんなに与えた価値に比べれば、1行のコードをどう書いたらきれいかだなんて1000分の1の価値もないよなー。つまりYoshiori GJ!!!

P.S. ついコメント欄のコードだけ見てつっこんでから気づいたけど、OAuthのどこに「ソートしてから結合したい辞書」が出てくるんだ?


id:showyou OAuth関連のパラメータ(oauth_signature_methodとかoauth_nonceとか)を送るときにはパラメータをソートした状態で送んないとダメ

なるほど、順番が変わるとハッシュ値が変わってしまうからかな。



id:agricola Python, あほか urllib.quote()でクォートした文字列を=で連結してるのに%使えば文字列以外もOKとは的外れな。元コードの意義は否定しないが、リスト内包で可読性を低下させて技巧に走ったのに美が無いのはいただけない。

(つд⊂)ゴシゴシ (;゚д゚) (つд⊂)ゴシゴシ

挙動が100%イコールじゃないよ、って書いただけなのに的外れって言われた。ふむ。はてブに書いてあったコードと等価なコードが元記事のどれなのかわからなかったのではてブに書かれていたコードが受理できる入力なら何でも受理できるように書いたというだけの話。日本語がよくわからないけど「リスト内包で可読性を低下させて技巧に走ったのに美が無い」って、もちろん僕のことじゃないよね?自虐コメントかー。


某チャットより転載(改行詰めたり誤植直したり言葉補ったりしてあります):

tokibito: ところで内包表記の元記事の該当のコードって


# パラメータをソートし,URIエンコードした key=value の形にして & で繋げます
params_str = '&'.join(['%s=%s' % (urllib.quote(key, ''),urllib.quote(params[key], ''))
for key in sorted(params)])
これ?
西尾泰和: そうなの?だったら僕の書いたコードとほぼ同じじゃない?これを添削して(quoteとかをすてて)はてブコメントのあれになってたの?それってquoteすてたから綺麗になったんじゃないの…
tokibito: そもそもurlencodeでいいような気がした
西尾泰和: urlencodeは忘れたが、なんかこういうの標準ライブラリにすでにありそうな気はした。urlencodeか。
tokibito: urllib.urlencode
西尾泰和: >Convert a mapping object or a sequence of two-element tuples to a “percent-encoded” string
西尾泰和: これでいいじゃんね
tokibito: ソートしたタプルを渡してもいいし、順序保証付きの辞書使ってもいいし。本気で書くならそうする
西尾泰和:

>>> urllib.urlencode([(k, d[k]) for k in sorted(d)])
'a=k&b=j&c=i&d=h&e=g&f=f&g=e&h=d&i=c&j=b'
したかったことはこうなの?
tokibito: だと思うんだけどどうだろう。そもそも内包表記に関する指摘が蛇足な感じか
西尾泰和: っていうか元コードのどれに対する指摘なのか読んでなかったんだけど、元コードを変に添削したのを僕が元コード見ずに添削したら元コードとほぼ同じに戻ったってこと?
tokibito: そんな気がする


チャット続き

yoshiori: urllib.urlencodeは、駄目だお。スペースを + にしちゃう。あと、外の指摘で判明したんだけど、 ~ もエスケープしちゃだめ
yoshiori: http://tools.ietf.org/html/rfc5849#section-3.6
yoshiori:


>>> urllib.urlencode({'foo':'bar hoge'})
'foo=bar+hoge'
>>> urllib.quote('bar hoge','~')
'bar%20hoge'

あとはてブコメントでも:

id:mattn urlencodeは内部でquote_plus使うので%20の結果が違って認証失敗するんじゃないかな。あと、quoteでちゃんとやるなら urllib.quote(s, safe='~') かも

thanks!