2013年1月26日土曜日

PythonでFizzBuzzとかしてみた

前回のエントリーでFizzBuzzをやる宣言したので帰りの電車の中で書いてみました。

まずは思うがままに書いてみた
int = int(raw_input("Please enter an integer: "))

def do_fizz(int):
    if (int % 3) == 0:
        return 1
    return 0

def do_buzz(int):
    if (int % 5) == 0:
        return 2
    return 0

def do_answer(fizz, buzz):
    flag = fizz + buzz
    if flag == 0:
        print int #引数に居なくても外のintを参照出来る
    elif flag == 1:
        print "Fizz"
    elif flag == 2:
        print "Buzz"
    elif flag == 3:
        print "FizzBuzz"

do_answer(do_fizz(int), do_buzz(int))
ちょっと変わったことしたいなーとか思ってるうちに何も出来ずに完成するという例w
後から文言変えやすいようにしてみたつもり。
Pythonは変数のスコープは内から外が参照できるのでintを引数にしてなくてもprintの際は参照出来ます。
でコレ書いた後、「Pythonって三項演算子どうやるんだろ?」って思ったんで調べて使ってみた。

int = int(raw_input("Please enter an integer: "))
flag = range(2) #Listのデータを入れ替えるのに宣言しないと出来なかった…
flag[0] = ((int % 3 == 0 and 1) or 0)
flag[1] = ((int % 5 == 0 and 2) or 0)

def do_answer(fizz, buzz):
    flag = fizz + buzz
    if flag == 0:
        print int
    elif flag == 1:
        print "Fizz"
    elif flag == 
        print "Buzz"
    elif flag == 3:
        print "FizzBuzz"

do_answer(*flag) #[fizz, buzz]のListが渡ってる
ついでに関数の引数をListで与える方法も試してみた。
ただこの場面での使い方があまりにもダサくてこれだったら普通に
fizz = ((int % 3 == 0 and 1) or 0)
buzz = ((int % 5 == 0 and 2) or 0)
って書いて渡した方がキレイですね。
phpの
$flag[] = (int % 3 == 0) ? 1 : 0;
$flag[] = (int % 5 == 0) ? 2 : 0;

$flag['fizz'] = (int % 3 == 0) ? 1 :0;
$flag['buzz'] = (int % 5 == 0) ? 2 :0;
みたいにいきなりList(配列)を作る書き方がPythonでも出来ると思うんだけど知識不足。
公式チュートリアルやったらどっかで出てくるかな?w

で最後はみんな大好き再帰。
折角なのでループ文を使わずに与えられたintまでの1からの和を出してみました。
num = int(raw_input("Please enter an integer: "))

def sum(num, answer = 0):
    answer = answer + num
    num -= 1
    if num == 0: return answer
    return sum(num, answer)

print sum(num)
等差等級の和は方程式出るのでループ回さなくても解けるのでそっちも試してみた。
start = int(raw_input("Please enter an integer: "))
end = int(raw_input("Please enter an integer: "))
print (start+end)*(end-start+1)/2
関数の定義すら要らなかったw
やっぱアルゴリズムの最適化が一番大事ってことですね!!

ということで帰りの電車の中で出来るPythonでした。
気軽に楽しめるのでみなさんもお好きな言語でどうぞ。

2013年1月24日木曜日

第一回 岡山Python勉強会の振り返り

先日、第一回 岡山Python勉強会を行いました。

まずは場所を提供してくださったシステムヨシイさん、ありがとうございました!!

そして主旨としては「Python初心者(主に自分)がPython使うようになる」ための勉強会です。
なので「Pythonすげーよ!みんな教えるから使ってよ!!」とか「Pythonでこんなことできるから誰か聞いて!」みたいな良くあるセミナー形式ではなく「俺、初心者だけどPython面白そうだから一緒に勉強しようよ!」ってスタイルで公式チュートリアルの第1章から第4章までのハンズオンを行いました。
(次回以降もこのスタイルの予定です)
なので参加者はバリバリのPythonistaな人からPython初めてな自分まで幅広く8人揃いました。
個人的にはマサカリをブンブン投げられて血まみれになるかと思っていましたが和気藹々と楽しく意見交換しながら進めることが出来ました。
今回特徴的だったのは

他の言語との言語仕様と比べることでよりPythonが際立って見えたこと

ですね。
例えばJavaだとこうだよねー、とかPHPはキーワードで関数の引数渡せないから不便、みたいな意見が出ることでPythonって言語仕様がより明確に見えた気がしました。
あと、Rubyはなんでも出来る実装だなと改めて思いましたw

というわけで今回やったチュートリアルのおさらい
今回、自分が気になったところだけ抽出して書きますがほぼ公式チュートリアルの写経です。
読んで気になるところは公式チュートリアルを見ながら是非ハンズオンしてみてください。

1. やる気を高めよう

・小宇宙(コスモ)高めるの大事
・後、英語力大事...(震え声

2. Python インタプリタを使う

・引数の受け渡しにはargvを使う
スクリプトで呼んだ際はargv[0]はフルパスが格納されてる
・実行権限のあるPythonファイルの先頭行に

#!Pythonへのpath

と記述するとPythonスクリプトをシェルスクリプトのように実行できる
#!/usr/bin/python

print 'test'

./test.py ←実行権限のあるtest.pyを実行

結果
test

3. 形式ばらない Python の紹介

・電卓を使うときはScalaやcalcを使わずPythonを使う
# 整数の除算は floor (実数の解を越えない最大の整数) を返す:
>>> 7/3
2
>>> 7/-3
-3
# 浮動小数点数を使った場合は浮動小数点数を返す:
>>> 3 * 3.75 / 1.5
7.5
# 型が統一されていない状態で浮動小数点数を使っていた場合は浮動小数点数を返す:
>>> 7.0 / 2
3.5
>>>x = y = z = 0  # x と y と z をゼロにする
>>> x
0
>>> y
0
>>> z
0
・複素数が計算できる
・\(バックスラッシュ)で終わる行は次の行が継続行として扱われる
・対になった三重クォート """ または ''' で文字列を囲むことでヒアドキュメントのような複数行にまたがった文字列が書ける
print """
だだだ
じじじ
ずずず
ででで   どーーーーーーーん
"""
結果
だだだ
じじじ
ずずず
ででで   どーーーーーーーん

・文字列は + 演算子で連結させる (くっつけて一つにする) ことができ、 * 演算子で反復させることができる
>>> word = 'Help' + 'A'
>>> word
'HelpA'
>>> '<' + word*5 + '>'
''

# 隣あった二つの文字列リテラルは自動的に連結されます: 
>>> 'str' 'ing'             #  <-  これは ok
'string'
>>> 'str'.strip() + 'ing'   #  <-  これは ok
'string'
>>> 'str'.strip() 'ing'     #  <-  これはダメ
  File "", line 1, in ?
    'str'.strip() 'ing'
                  ^
SyntaxError: invalid syntax
・文字列のインデクス表示
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'

>>> word[:2]    # 最初の 2 文字
'He'
>>> word[2:]    # 最初の 2 文字を除くすべて
'lpA'
# インデックス指定された文字列中のある位置に代入を行おうとするとエラー:
>>> word[0] = 'x'
Traceback (most recent call last):
  File "", line 1, in ?
TypeError: object does not support item assignment
>>> word[:1] = 'Splat'
Traceback (most recent call last):
  File "", line 1, in ?
TypeError: object does not support slice assignment

# 文字列同士の内容を組み合わせた新しい文字列の生成は、簡単で効率的:
>>> 'x' + word[1:]
'xelpA'
>>> 'Splat' + word[4]
'SplatA'
・インデクスを負の数にして、右から数えることできる
>>> word[-1]     # 末尾の文字
'A'
>>> word[-2]     # 末尾から 2 つめの文字
'p'
>>> word[-2:]    # 末尾の 2 文字
'pA'
>>> word[:-2]    # 末尾の 2 文字を除くすべて
'Hel'
・リストの使い方
>>> a = ['spam', 'eggs', 100, 1234]
>>> a
['spam', 'eggs', 100, 1234]
>>> a[0]
'spam'
>>> a[3]
1234
>>> a[-2]
100
>>> a[1:-1]
['eggs', 100]
>>> a[:2] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]
>>> 3*a[:3] + ['Boo!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boo!']
# リストは個々の要素を変更することができる:
>>> a
['spam', 'eggs', 100, 1234]
>>> a[2] = a[2] + 23
>>> a
['spam', 'eggs', 123, 1234]
>>> # いくつかの項目を置換する:
... a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]
>>> # いくつかの項目を除去する:
... a[0:2] = []
>>> a
[123, 1234]
>>> # いくつかの項目を挿入する:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> # それ自身 (のコピー) を先頭に挿入する
>>> a[:0] = a
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
>>> # リストをクリアする: 全てのアイテムを空のリストに置換する
>>> a[:] = []
>>> a
[]
# リストの入れ子(多次元)もできる
>>> q = [2, 3]
>>> p = [1, q, 4]
>>> len(p)
3
>>> p[1]
[2, 3]
>>> p[1][0]
2
>>> p[1].append('xtra')     # 5.1節を参照
>>> p
[1, [2, 3, 'xtra'], 4]
>>> q
[2, 3, 'xtra']
>>> # Fibonacci 級数:
... # 二つの要素の和が次の要素を定義する
... a, b = 0, 1
>>> while b < 10:
...     print b
...     a, b = b, a+b
4. その他の制御フローツール
#if文
>>> if x < 0:
...      x = 0
...      print 'Negative changed to zero'
... elif x == 0:
...      print 'Zero'
... elif x == 1:
...      print 'Single'
... else:
...      print 'More'
ちょっとelifは違和感・・・
>>> # いくつかの文字列の長さを測る:
... a = ['cat', 'window', 'defenestrate']
>>> for x in a:
...     print x, len(x)
cat 3
window 6
defenestrate 12
リストの数でループが回るのでforというよりはeachですね。 しかも文字列を与えた場合は文字数でループします。 intの場合はerrorです。 条件式でループさせたい場合はwhileになります。
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5, 10)
[5, 6, 7, 8, 9]
>>> range(0, 10, 3)
[0, 3, 6, 9]
>>> range(-10, -100, -30)
[-10, -40, -70]
range()は条件が矛盾(stepとendの正負が違って終了しないなど)してる場合は空を返す ・関数の定義
>>> def fib(n):    # n までのフィボナッチ級数を出力する
...     """Print a Fibonacci series up to n."""
...     a, b = 0, 1
...     while a < n:
...         print a,
...         a, b = b, a+b
...
>>> # 今しがた定義した関数を呼び出す:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
>>> def fib2(n): #  n までのフィボナッチ級数を返す
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # 下記参照
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # 関数を呼び出す
>>> f100                # 結果を出力する
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

#デフォルトの引数値
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
    while True:
        ok = raw_input(prompt)
        if ok in ('y', 'ye', 'yes'):
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise IOError('refusenik user')
        print complaint
●必須の引数のみ与える: ask_ok('Do you really want to quit?') ●一つのオプション引数を与える: ask_ok('OK to overwrte the file?', 2) ●全ての引数を与える: ask_ok('OK to overwrte the file?', 2, 'Come on, only yes or no!') ・関数を keyword = value という形式のキーワード引数を使って呼び出すこともできます
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"

# 以下のいずれの方法でも呼び出せます
parrot(1000)
parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
parrot('a million', 'bereft of life', 'jump')

# しかし、以下の呼び出しはすべて不正なものです
parrot()                     # 必要な引数がない
parrot(voltage=5.0, 'dead')  # キーワード引数の後に非キーワード引数がある
parrot(110, voltage=220)     # 引数に対して値が重複している
parrot(actor='John Cleese')  # 未知のキーワードを使用している
・キーワード引数が入った辞書を使った方法 これが一番気持ち悪いって好評だったw
def cheeseshop(kind, *arguments, **keywords):
    print "-- Do you have any", kind, "?"
    print "-- I'm sorry, we're all out of", kind
    for arg in arguments:
        print arg
    print "-" * 40
    keys = sorted(keywords.keys())
    for kw in keys:
        print kw, ":", keywords[kw]

# 呼び出し
cheeseshop(
           "Limburger",
           
           "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")

# 結果
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch
13行目は文字列 kind 15行目と16行目はリスト *arguments 18~20行目はkey=valueな辞書 **keywords となっています。 リストは必ず辞書よりも前にある状態でないと渡せないので混合して使う際は注意が必要です。 混合して使うやり方は慣れてない人には一見して判断出来ないので難しいかもですね。
>>> range(3, 6)             # 個別の引数を使った通常の呼び出し
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args)            # リストからアンパックされた引数での呼び出し
[3, 4, 5]

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print "-- This parrot wouldn't", action,
...     print "if you put", voltage, "volts through it.",
...     print "E's", state, "!"
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
こんな辞書の使い方ならわかりやすくていいと思います。
phpもこういう引数の渡し方が出来るようになって欲しいですね。
それと変数のスコープですが関数の内から外は参照できます(関数の外の変数も)
また関数がネストしてる場合も内から外は参照できます。
ですが外から内は別のスコープになるので関数内で利用してる変数は呼べません。
(補足ですが未定義の変数はPythonではerrorになります)
・ラムダ式
うーん、紹介されてる使い方はピンと来なかった。
無名関数を変数に格納する方が自分は使う気機会が多いからかな?

と気になったところを自分の復習も兼ねてまとめました。
当日はこんな感じをそれぞれの環境で実行しながら確認して、その場その場で質問や意見を交換してました。
これを最後を読んだ人は前回のハンズオンとほぼ同様なのでいきなり次回から来ても全然問題ありません!
ということで次回は同様にシステムヨシイさんで2月26日(火)19:30から予定してます。
多分5章をじっくりやることになると思います。
僕はこれだけあればFizzBuzzが書けるのでこの週末にでもPythonで書いてみようと思います。
ちょうど土曜にRuby勉強会が岡山であるから会場でPythonだな(問題発言
ということで次回も楽しみにしてます!!

2013年1月22日火曜日

オープンセミナー2013@広島を開催して

OSH2013を終えた感想。

当日のTwitterの様子は #OSH2013 のハッシュタグのまとめをどうぞ。

講師の方のセッション情報はこちら(セッション順)

随時追加予定

谷 雅彦さん



佐藤 慎也さん

残念ながら資料は非公開となります(´・ω・`)

大垣 靖男さん

大垣さんのブログに資料が置いてあります。

大西 彰さん



櫻庭 祐一さん



ソースコード

まずは大変興味深い、刺激的なセッションをしていただいた講師の皆様、ありがとうございました。
参加していただいた参加者の皆様、ありがとうございました。
そして運営を手伝っていただいたスタッフ、また告知活動や当日の手伝って下さった友人の皆様、ありがとうございました。

本当にこのオープンセミナー広島@2013が無事終えることが出来たのは多くの方のお陰です。
この感謝の気持ちが最初にイベントを終えてまず感じたことでした。
あとは

   広島にはまだまだ見ぬ面白い人がいっぱいいる

これですね。
中国地方のIT業界の話題は大都会岡山に押され気味と感じる広島県。
でも今回イベントを行なってみて、人の母数の多さを感じました。
多くの人が今は「面白い部分を見せるきっかけ」がないだけだと思います。
なので今後ももっと色んな形のイベントを通して繋がりを増やせたらと思ってます。
まずは周囲の人をもっともっと巻き込むところからかな(チラチラ
スタッフ、絶賛募集中!です。

というわけで来年もOSHをよろしくお願いします。
そして来年のOSHの実行委員長は@eielhさんです。
どんなイベントになるか今から楽しみですね!
またコンテンツが決まった際はこちらの公式サイトを更新していく予定です。
Twitterや公式サイトなどで意見も頂けたら嬉しいです。
公式サイトのソースはGithubを利用してるのでこちらも興味がある人はforkしてみてください。
それでは@eielh先生の次回作にご期待ください。