2012/05/11

pythonで繰り返し作業 ~for-inループ編~

コンピュータに仕事をさせて人間は楽をしたい(笑)。これがプログラム的なものを仕込む(あるいは勉強する)目的であり醍醐味だと思います。

今回は、コンピュータがいかにも得意そうな「作業の反復」について書いていきたいと思います。
この内容、たいていのプログラム本で関数の項の前くらいに見かけることが多い気がしますが、mel本では取り上げていませんでした。[*1]

反復や、条件による分岐など、処理内容の流れ方に関することをまとめて「制御構造」と読んだりします。字面がイカツイですが、「制御についての構造」…と考えると、うーんなんとなく分かる気も、というところでしょうか。英語では「control structure」です。こっちのほうがわかりやすいような気もしますね。

制御構造にはいろいろあるので、何回かに分けて書いていくことになるかと思いますが、
今回はもっともよく使うであろうfor-inループについて解説します。





for-inループは、ある集合(たとえば複数個のポリゴン球)のそれぞれに、同じ内容の処理を適用するときに使います。指定した集合のなかみ全部にてっとり早くかかります。

基本的な構造は以下のようになります↓


for ○○○ in □□□ :
    処理する内容~~

※解説用に全角記号などが入っていますが、もちろん実際には半角英数だけで記述してください。

まず □□□ ですが、ここに処理の対象となるリスト・配列を書きます。
○○○は「繰り返し用の変数」で、□□□集合から抜き出された処理対象一個が、ひとまずここに入ります。
で、二行目(もしくは二行目以降)で○○○に対して行われる作業について書いていきます。
ここの処理部分には、○○○が含まれていなくてもそれはそれでかまわず実行されます。

慣れないうちは□□□と○○○ではどっちがなんだったっけ?と思っていまいそうですが、
○○○ in □□□ というくらいですから、
集合□□□「の中の(in)」○○○ に対してこれからどうするのか、というイメージで、in □□□ の方が数の多い方というか、あつまり全体、○○○は、取り出した一個が暫定的に入る場所、という感じで覚えるといいかと思います。

ここで、python的な書き方のルールについて。


for ○○○ in □□□ :


の最後の「:」を記入すること、それからその後の


    処理する内容~~


ここが、タブで一段下がっていること。
これがpythonでは大事です。
この一段下げることを「インデント」といいますが、
pythonではインデントも重要な入力内容の一つです。

というのも、melや他の多くの言語では、上記のような仕組みを記述するときは


~~{
    処理内容
    }


と「」「」で囲んでいました。こうすることで内容がどこから何処までなのかを明示し、だいたいの場合改行やインデントは見やすくするために入れるようなもので、あってもなくてもかまわないくらいでした。
pythonではそうした{かっこ}で囲んで内容の開始終了を明示する代わりに、インデントにその役割をもたせています。インデントの有無が処理内容のまとまりを示すことになります。

pythonは文化的に「同じ内容なら誰が書いてもだいたいおなじになる」ように設計されており、それがこういった部分に現れています。また結果的に、コードは見やすく整理された状態で記述されることになります。こうすることで書いたものがお互いの参考になりやすく、オープンな地盤を強化するのに一役買っていると思われます。

このインデントによる内容明示は、反復だけでなく条件分岐や、もちろん関数でも使われます。

~~:
    処理内容

という基本形は必須のかたちということで覚えておきましょう。
(pythonでの関数もこのブログで追って取り上げる予定です)

ちなみにスクリプトエディタでタブを入力すると、実際には半角スペース4つ分が入力され、インデントされているパートで改行を入れると、そのインデントにそろった状態で次の行に移ることができます。
タブではなくスペース4つを入力して記述を開始しても、タブを入力してインデントしたのと同様に扱われ、改行の際にもインデントを揃えてくれます。


さて、では簡単なサンプルを↓


testlist = ['a','i','u','e','o']

for testchar in testlist:
    print ( testchar )


 

実行すると、a i u e o が位置文字ずつ改行されて表示されます。
一行目で、処理の対象となる集合を testlist という変数の中にいれています。ここでは簡素に1文字ずつのリストです。pythonですので型の宣言は不要です。この場合は自動的にlist型になります。(文字列を「'」で囲むのを忘れないでください。文字列として認識されると、スクリプトエディタでは黄色で表示されるようになります。)

二行目 for testchar in testlist: でfor-inループの開始です。
testlist がさきほど作った、処理の対象になる集合。testchar が、ループ中にtestlistの要素一個一個がいれられる変数です。

三行目 反復させる処理の内容です。printを使ってtestcharの中身を表示させています。ここはとってもそのまんまですね。

実行してみたところ

それでは、もうちょっとmayaっぽい例いってみましょう↓


import pymel.core as pm
import random

nameList = ['a','i','u','e','o']

for testName in nameList:
    pm.polySphere(n = testName, r = random.random())



基本的な仕組みは一緒ですが、事前にpymelrandomのモジュールを読み込んでいます。そしてfor-inループ内でpolySphereを実行し、そのときr(radius、半径)にランダムな値が入るようにしています。
実行すると、nameListで指定した個数だけ(ここではnameListに5つの要素を入れているので、五個)、半径ランダムなポリゴン球が作成されます。

実行してみました。半径ランダムな球が作成されます。

さて…
ここでは名前を事前に指定し、その個数だけ球が作成されるようにしました。
では、とりあえず名前はいいので指定した個数分球を作って欲しい、という場合にはどうしたらよいでしょうか…??

つづきます。



■関連リンク

PyMELドキュメント内 polySphereのページ

Maya Python @Maya2012 オンラインドキュメント

pythonチュートリアル for文 @日本pythonユーザ会 Python 2.7ja1 documentation




[*1] どこかでも述べていますが、mel本では基本的にmelの入門のしやすさに着目して取り上げており、入門をくぐり抜けて今後深入りするならpythonです。
この反復の部分に限らず、melとpythonでは書き方のスタイルに違いがありますので、もしかしたら使わなくなるかもしれないmel式の書法などは勉強しても…と考えて、mel本では省いたという経緯があります。

0 件のコメント:

コメントを投稿