10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby経験者のPython ハマりポイント(with文とスコープ)

Last updated at Posted at 2018-07-16

個人的に誤解していたので記載しておきます。

最初に結論

Pythonのwith文は、Rubyのブロック(do-end)と似ているが別物。
Rubyのブロックと違ってPythonのwith文はスコープを生成しない。

例えばファイルを扱う処理で「自動的にファイルを閉じる」という目的が達成できるという点では同様だが、変数のスコープとしては意識しておく必要がある。

環境

OSはmacOSで確認(そもそもOSに依存しない)。

$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
$ python3 -V
Python 3.7.0

with文(構文?)が使えるようになったのはPython 2.5以降らしい。

具体例

まずはRubyから。

irb(main):011:0> File.open('test.txt') do |file|
irb(main):012:1* a = 1
irb(main):013:1> end
=> 1
irb(main):014:0> a
Traceback (most recent call last):
        2: from /usr/local/bin/irb:11:in `<main>'
        1: from (irb):14
NameError (undefined local variable or method `a' for main:Object)

do-endの内部で定義した変数aはブロック内のローカル変数なのでスコープの外側ではアクセスできない。

別の言い方をすると、Rubyのブロックはスコープを作る(ただし、ifforなどの制御構文はスコープを作らない)。

Python の場合は以下のようになる。

IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: with open('test.py' ) as fp :
   ...:     a = 1
   ...:
   ...:

In [2]: print(a)
1

with文はスコープを生成しないのでこの変数aローカル変数ではない
制御構文の一種と捉えるか、try-except文(これもスコープを作らない)のシンタックスシュガーと考えておいたほうがいい。

PythonもRubyに共通して制御構文であるifforwhileもスコープを生成しない(C言語系の言語は違う)。

まとめ

C言語系のスコープとRubyのブロック、このあたりの区別ができていないとコードの読解で混乱します。

他にもハマりやすいぽいんとはありますが他の記事で解説されていると思うので省略。

参考URL

10
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?