re:annkara

日々学んだことを書き留めておく。

初めてのPython再挑戦2

初めてのPythonのメモがき。
今日はステートメントの部分のポイントをまとめる。

条件の評価式の際には()は任意

a = []
in not a:
    print a #空のリストが表示

代入ステートメントについて

代入は変数とオブジェクトリファレンスを結びつける操作のこと。 変数はオブジェクトリファレンスを保持するのみであり、 型情報はあくまでオブジェクト側で保持されていることに注意。

形式
  • シーケンス代入
a, b, c, d = "spam"
print a # 's'と表示
print b # 'p'と表示

左辺の変数の数と、右辺のシーケンスの要素数が一致しないとエラーなる。 そういう場合は、スライシングを利用すると良い。

str = "spam"
a, b, c = str[0], str[1], str[2:]
print c # 'am'と表示
  • マルチターゲット代入

複数の変数に同一のオブジェクトリファレンスを保持させることができる。

a = b = [] # a b ともに空のリストの共通リファレンスを保持する
a.append(1)
print a, b # ([1],[1])と表示

b.append(2)
print a, b # ([1, 2], [1, 2])と表示

いわゆる、+=や/=なやつ。
演算対象が可変オブジェクトである場合、ちょっと変わった振る舞いをする。

L = [1,2]
L = L + [3] # リストの連結 このとき新しいリストオブジェクトが生成され代入される
L = L.append(4) # appendを利用すれば元のオブジェクトの上書きをする

新しいオブジェクトを生成するか、上書きをするのか挙動が変化する。 このとき、拡張代入ステートメントを使用すれば、処理系が自動で実行速度で高率な方を採用するため、 あまり考えなくてよい。

printステートメント

オブジェクトのデータをテキストに変換して標準出力ステートメントに書き込むステートメント

標準出力の変更

sys.stdoutにwriteオブジェクトを備えたオブジェクトを代入すれば、printステートメントが リダイレクトされる。

>>でもリダイレクトは可能であるが、これは一度キリなので、何度もリダイレクトしたい場合は sys.stdoutを弄った方がよい。

forループ

forステートメントを使用しないループ処理の書き方もある。 処理対象のオブジェクトをiter()に渡すと、イテレータオブジェクトを返す。 そのオブジェクトに対して、nextメソッドを実行すると、要素を返してくれる。

L = [1,2,3]
I = iter(L) # 反復処理に対応したオブジェクトを生成

I.next() # 1を表示 要素がつきるとStopIteretion例外を発生させる

リスト内包表記

メリットとして、コードが簡潔になる。 また、処理速度もforループを使用したときよりも高速になる。 これは反復処理がPythonのコードレベルではなく、インタプリタの内部で Cのコードレベルで実行されるから。 デメリットとして、いくらでも拡張することができるため、複雑な処理を記述すると可読性が落ちてしまう点。

幸せなシステム開発って何だろうって考えたこと。

大層なお題目をたててみたけども、単なる愚痴に落ち着くんじゃないかと最初に述べておく。

最近関わっている仕事で、幸せなシステム開発って何だろうと思うことが多くて、 自分が普段不満に感じていることと、じゃぁどうすればいいの??ってとこをまとめてみたいと思う。 自分の今の職場がメインフレーム相手に開発してるという前提でのお話となります。

ドキュメントやソースコードのバージョン管理がされていない

これは今に始まったことじゃないんだけど、バージョン管理っていう概念がない、とまでは言わないけど バージョン管理ツールを用いて管理するっていう考え方がない。 エクセルの仕様書はリネームしたり、もしくは修正ページだけ記載したり、色をつけたりで管理したりする。 ソースにいたっても同様で、差分をとれるのは前回との差分、もしくは本番ソースのみ。

だから、頻繁に修正なんか入ったりすると、いつ、誰が、何のために、どんな修正したのか ということを人力で判断しないといけない。

今ならgitやSubversionでも導入して、管理していければいいんじゃないかなって思う。 もちろん、Web系の開発をしているチームでは当然に行われているけど、 いわゆるホスト系(メインフレームでの開発)のチームでは行われていないのが現状。 というか、必要性を感じていないのかなぁ。そういう声全然聞いたことないし。

適切な設計に基づいてソースが書かれていない

これはWebとかホストとか全く関係ないとは思うんだけど、いかんせんソースコードがばかでかい。 ひとつの機能を果たすモジュールのはずなのに、最終アウトプットを出力するための中間処理とかも そのモジュールに組み込んでいて、何がどこでどのように行われているのか全然わからない。 そしてグローバルスコープ万歳の状態。

そういうプログラムに限って、非常に重要な機能を果たしているため、 ちょっと修正するだけでも戦々恐々しながら修正している。

これは何だろうなぁ、、、自分もたいしたスキルを持っている訳じゃないから たいした事は言えないけど、オブジェクト指向とかデザインパターンとかリーダブルコードとか 良い設計の仕方、良いソースコードの書き方とか学んで行くしかないのかなぁって思う。

結局は開発者のスキルを高めることが大事なのか。 そういう意味ではスキルとか高めていこうっていう風潮ないんだよなぁ... いや会社としてはそういうことを謳っているのではあるんだけど、実際に働いている人がなぁ...

納得感のない開発

プロダクトが実際のお客さんに喜ばれるかどうか、逆に喜ばれないんじゃないかと思う開発を実施すること。 そういうプロダクトに限って非常に複雑な仕組みの商品で、システムの実装も非常に苦労するし、 こういうの作っても本当にお客さんに喜ばれんの??って思いながら開発するのは本当につらい。

んーこれはある程度の規模の会社になったらしょうがないのかなって思う。 誰もが納得するプロダクトって難しいよね。

とまぁつらつらと書いたけど

結局は、プロダクトが自分の納得がいくもので、会社としてもこういう状況だからこのプロダクトが必要なんだ、
とちゃんと説明してくれて、開発レベルでいえば適切な開発フローと開発ツールが用意されていて、ソースが汚くても
ちょっとずつリファクタリングしていって、奇麗にしていこうみたいな心構えがあれば幸せなんかなぁって思う。

いやまぁ、そういう会社って少なくない??理想高くない??って思うけど、別に開発フローやツールは自分たちで用意していけばいいし、
そもそもリファクタリングなんてCIツールやテストの自動化が前提にあると思うから、やっぱり納得感のいく開発が
できることが幸せなシステム開発の根幹なのかなぁって思った。
あとはあれか。会社としてもそういうのを許してくれる会社か。お金出すの会社だもんね。

そういう意味では、正しいタイトルは「企業に勤めるうえでの幸せなシステム開発」か。

全然まとまってないけど、とりあえず自分の中で大事だろうなぁって思ったのでまとめた次第です。

初めてのPythonに再挑戦。

dir関数
dir(module)

モジュール内で利用できる属性のリストを返す。

名前空間

変数(名前)の集合のこと。 Pythonはモジュール毎に名前空間が設定されていると言える。

Pythonにおける変数

変数は代入されることで初めて作成される。 また、変数に保持されるのはオブジェクトのリファレンスであり、 オブジェクト自身にオブジェクトの型情報や、被参照数(リファレンスカウンタ)、値を保持している。 このリファレンスカウンタがゼロになったさいに、ガーベージコレクタによって、 オブジェクトのメモリスペースが解放される。

静的型付言語では、変数にも型情報を保持していることになるのかな??

同等と同一

同等とは、オブジェクトの値が同じであること。 ==演算子を使用。
同一とは、変数のリファレンスが同じであること。 is演算子を使用。

ディクショナリを用いての文字列フォーマット
"" %(id)s : %(name)s " % {"id":"0001", "name":"taro"}""

キーを文字列に埋め込んで、フォーマットすることも可能。

ディクショナリについて

写像とは、要素にキーが割り当てられたオブジェクトのこと。
リストは、オブジェクトリファレンスの配列であるが、 ディクショナリは、オブジェクトリファレンスの順不同のテーブル。
ハッシュテーブルで実装されている。
リファレンスが保持されるという点では、一緒。

shallow copydeep copy

shallow copy
[:]やdict.copy()でコピーされるのは、トップレベルでのオブジェクトのみ。 なので、ネストされていた場合、そのオブジェクトのコピーはされない。

deep copy
copy.deepcopy()を利用すると、ネストされたオブジェクトリファレンスもコピーされる。 が、あまり使用しないらしい。

簡易RSSをPythonで自作した。

GoogleRSSリーダーを一時使用していたのだけど、サービスが停止してからRSSリーダーを一切使わなくなった。
いつか自作しようと思っていたのだけど、そのいつかは訪れることなく今の今まで来てしまったので、プログラミングの学習がてら簡易なリーダーを自作してみた。

使用したもの

簡単な説明

取得したいURLを記載したテキストファイルを準備して、それを読み込みparseして、タイトルとリンクをのみを取得し、htmlファイルへと出力する簡易な仕組み。

ソース

メイン的な。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import feedparser, file_handle

# html template
html = """
<p> %s </p>
<a href=%s> %s </a>
"""

# file 操作
file_input = file_handle.open_file("url_list.txt")
file_output = file_handle.make_file()

#main処理 feedparserを利用して、タイトルとurlをhtmlファイルに出力する。
for line in file_input:
    res = feedparser.parse(line)

    for entry in res.entries:
        title = entry.title.encode('utf-8')
        link = entry.link.encode('utf-8')
        file_output.write(html % (title, link, link))

ファイル操作するやつ。

def open_file(path):
    return open(path, 'r')

def make_file():
    import datetime
    today_html = "./rss_html/" + str(datetime.date.today()) + ".html"
    return open(today_html, "a")

ちょっと文字コードあたりで苦労したので、そこらへんをちゃんと理解していきたい。
あと便利なものを使うのもいいんだけど、学習っていういみでは元々の仕組みをしることも大事だと思った。

みんなのPython Webアプリ編でつまった点など

ヘッダー部分とコンテンツ部分に改行が必要な点

self.headers = {'Content-type':'text/html;charset=%s\n' % charset}

\nがないと、ブラウザからアクセスしても画面が真っ白に。

Everyday FunkiEE!!

この記事で解決。 でも、なんで改行しないとだめなんだろ??

Permission周りで権限がないと弾かれる点

Python CGIHTTPServer crashes with “OSError: [Errno 13] Permission denied”

なんとなくこうすれば良いということはわかったのだけど、根本的なところが理解できてない。
Pythonの話ってよりは、OSの権限周りの話なのかな。

ソースコードを読むという意味でも、ここらへんのソースを追いつつ、OS周りのことも調べていきたい。

とりあえず、rssのurlを入力して、記事を得るという機能までは満たせたけど、
ソースの理解はまだまだなのでここからもう一歩踏み込んでいきます。

Python覚え書き

パーフェクトPythonの昨日の続き。 初めてのPythonなどを参考にメモしてます。

with/asステートメント

try/finallyステートメントの代替として設計されたもの。 異なる点として、より幅広い用途に対応できるオブジェクトのプロトコルをサポートしている点が異なる。

基本的な使い方

with expression [as variable]:
    with block

expressionにはコンテキスト管理プロトコルをサポートするオブジェクトを戻すコード が入り、asを用いると、variableには何らかの値が代入される。 このとき、variableに代入されるのはコンテキスト管理プロトコルをサポートするオブジェクトではないことに注意。 このオブジェクトは、withブロックが開始され前に「前処理」をすることもあるし、終了後に、「後処理」をすることもある。

具体的な処理

with open("path/to/something") as f:

とした場合に、openはファイルオブジェクトを返し、それがfに代入される。 ファイルオブジェクトは、コンテキスト管理プロトコルをサポートしているため、 withブロックを抜けたら、自動的にファイルはクローズされる。

ちょっと紛らわしかったけど、要するに、expressionは評価された値じゃなくて、 オブジェクトを返して、asが使われていたら変数にオブジェクト代入するよっていう代物か。

コンテキストマネージャ

with/asの使い方は理解したけど、コンテキストマネージャって何だろう。 これは、初めてのPython見ても記述が見当たらなかった。

今まで整理した内容から考えると、ある操作をするときの状況・文脈で必ず行いたい前処理や後処理を 定義したもののことを言うのかな??

ちょっとここらへんまだ曖昧です。

とりあえず、独自のコンテキストマネージャを定義することができることは理解した。

クロージャ高階関数

クロージャ

すでに存在しない外側のスコープに属する変数を保持しているオブジェクトのこと。

def outer():
    x = 88          # 外側の変数
    def inner():
        print x      # 外側の変数を参照
    return inner  # 内側の関数オブジェクトを返す

action = outer() # 関数呼び出し。innerオブジェクトを返す。
action()              # 関数呼び出しにて、88と表示。

すでに存在しない、つまりはaction()を呼び出した際に、outer()は既に存在しないが、 inner()はouter()の変数xの値を保持している、ということ。

基本的にネストされた関数はわかりづらくなりやすいので、避けた方が無難ぽい。

高階関数

こっちは昨日の理解でよさげ。 なので、apply関数とか、map関数とかをサンプルに記述する。

def func(x, y, z): return x + y +z
    apply(func, (2, 3, 4,)) # 9と出力

list = [1, 2, 3, 4]

def inc(x): return x + 10
    map(inc, list) # [11, 12, 13, 14]と出力

apply関数は関数オブジェクトと引数を渡すことで、関数を実行してくれる。 map関数は、関数オブジェクトとシーケンス型のオブジェクトを渡すことで、 一つ一つの要素に関数を適用して、リストを生成する。

デコレータ

とりあえず、以下のリンクを見る。

Python 用語集

(デコレータ) 別の関数を返す関数で、通常、 @wrapper 構文で関数変換として適用されます。 デコレータの一般的な利用例は、 classmethod() と staticmethod() です。 デコレータの文法はシンタックスシュガーです。次の2つの関数定義は意味的に同じものです:

def f(...):
    f = staticmethod(f)

@staticmethod
def f(...):

とりあえずここまでは理解。 具体的なサンプルコードを見てみる。 以下のリンクを見てみる。

Pythonのデコレータを理解するための12Step

具体的なサンプルコードはリンク先を見てもらうとして、 要するにデコレータっていうのは、関数本体に手を入れることなく、何か別の事をやって欲しいと思ったときに、 それ専用のクロージャを作ってあげて、何かごにょごにょして、ハイじゃあ元の関数さんあなたの仕事してねって 感じの処理か。

それぞれの関数内で、ごにょごにょする関数を呼び出してもいいけど、@関数名でデコレートしとけば、 見た目奇麗になるでしょ、てな感じで今は理解しておこう。 (ここら辺からだいぶ適当になる、かも)

ディスクリプタ

参考にしたリンク先
ディスクリプタ HowTo ガイド
Python を支える技術 ディスクリプタ編 #pyconjp

__get__,__set___,__delete__

上記、3つのメソッドを定義したオブジェクトのこと、、、、

とまではわかったけど、それ以降は全然理解できない。

ちゃんとPythonにおけるクラスとかの仕組みを理解しないとだめな気がする。 ということで、もいっかい勉強し直してからここは戻ってこよう。

メソッド関連の話もそれからということで。

昨日今日とPythonの学習してきたけど 今まで言語の表面的な部分しか全然触ってきてなかったんだなと痛感しました。

それでも内部的な仕組みに少しでも触れることができたので、 今後とも精進していきたいです。