スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ブログお引越し

お久しぶりです。
ここ最近記事書いてなかったのに、久しぶりに書いた記事がお引越しのお知らせとは。

GoogleのBloggerが使いやすかったので移行しました。
お手数ですがブックマークの変更をお願いいたします。

金星☆ちゃんねる (日本語)
http://venuschjp.blogspot.jp/

VENUS CHANNEL (英語)
http://venusch.blogspot.jp/

日本語と英語でブログ分けました。
これからもよろしくお願いします。
スポンサーサイト

テーマ : お知らせ
ジャンル : その他

Python:グローバル変数 -Global Variables-

Tell the readers who do not read Japanese
Important thing is translated in English that is colored green.
I'm not good at English,so I apologize you if you struggle to read my page.
Summary:
This page is written about global value on Python.
You have to declare a 'global' to use global variables in Python.
I show some example ,and in last describe how to use global variables in class.

 こんばんは。
ここしばらくロボットではなくPythonの話ばかりですね。
でもブログとかに書いておかないと忘れちゃうのでご勘弁を。

では今日はPythonでのglobal変数の扱いです。
C言語のようにアクセスするとハマるので確実に一回は検索することでしょう。
そして、検索しても見つからなかったクラス内のグローバル変数の使い方について書きます。
(たぶんちょっと考えればわかるからあえて書いてないのかもしれませんが・・・)

それでは早速一番基本的な使い方を示します。
関数内でglobal宣言することで、グローバル変数を使用できます。
I show how to use simple global variables.
You can use a global variables by declaring a 'global' in the function

>>> def gl_test1():
        global g1
        print g1

>>> gl_test1()
0


次に、グローバル変数の値を変更してみます。
値が保存され、呼び出しのたびに加算されているのがわかります。
Next I try to change the value of a global variables.
You can recognize that saved the value adding one to every call.

>>> g2 = 0

>>> def gl_test2():
        global g2
        g2 += 1
        print g2

>>> for i in range(10):
        gl_test2()

1
2
3
4
5
6
7
8
9
10


最後に、クラスからグローバル変数を使う例を示します。
このように'self'を付けないとクラス内でグローバル変数にアクセス出来ません。
またグローバル変数を使うときは、安全性を考えてメソッドを使って値のやり取りをするのがお行儀の良いプログラムらしいです。
なので一番最後のように直接アクセスするような使い方はやめましょう。
Last, I show example of using global variables at Class.
You can access a global variables from the class by putting 'self' as an example.
I recommend that you access to the global variables via the method.


>>> class GlTest(object):
        g = 0
   
        def get(self):
                global g
                return self.g
        
        def add(self, x):
                global g
                self.g += x

>>> gc = GlTest()
>>> gc.get()
0
>>> gc.add(100)
>>> gc.get()
100
>>> gc.g
100


地味にこのselfをつけるのがわからず少し悩んだので書いておきました。

ちなみに今回から記事の一部を英語化しました。
これはアクセス解析したら外国の人もいるということがわかったのと、英語の勉強です。
英語間違ったり、不自然だったりしたら教えてください。
それでは今回は以上です。
Thanks you for read my page.

テーマ : プログラミング
ジャンル : コンピュータ

Python:ビット演算

 こんばんは。今回もPythonです。

最近は、苺サーボ(PRS-40M)をPythonから制御しています。
昔はマイコンから制御して実験していたのですが、Pythonだと効率良く開発が進みます。
その時にハマった、C言語辺りからPythonに入った人が陥りやすい罠ついて書きます。

コマンド式サーボモータはコマンド生成や、データを読み込む時によくビット演算を用います。
負の値として苺サーボは二の補数表現を用いています。
これは1の負数である-1を表現するなら以下のようにな流れになります。

① ビット反転する
② 反転した数字から1を足す

これを実際にPythonで実行します。


>>> ~1 + 1
-1


正しそうな値が出てきました。

次に、苺サーボの現在位置を複合してみます。(苺サーボは現在位置を16bitのデータとして送ってくる。)
複合の手順は逆にたどり最後にマイナスを掛けます。
① 値から1引く
② ビットを反転する
③ 値に-1を掛ける(複合した値は正の数のため)

それでは実際に負の限界値である-3600(二の補数表現で61936)を複合します。


>>> ~(61936 - 1)
-61936


①と②を実行しただけでもうすでにおかしいです。
負の値になっています。何が問題なのでしょうか。
疑問としては桁数が不明なPythonでどのよにビット反転をしているのでしょうか?
二の補数表現は一番上位のビットを1にする決まりですが、一番上位とは変数のサイズが決まらないPythonでは表現できません。

そこでPythonではビット反転演算を以下のように定義しいるそうです。


-(値 + 1)


これなら納得です。最初の値が合って、現在位置の複合がうまく行かない理由がわかります。
実際には何が悪いのかわからずかなり戸惑いました。
C言語上がりの私には、こんな罠があるとは思いもしませんでした。

そこでビット反転はXORを使ってやることにします。


>>> -((61936 - 1) ^ 0xFFFF)
-3600


現在位置は16bitとわかっているので、0xFFFFでビット反転することが出来ます。



1111 0001 1111 0000 :-3600の二の補数表現
1111 0001 1110 1111 :-1した値

1111 1111 1111 1111 :0xFFFF

0000 1110 0001 0000 :XORした値(1がひとつだけあるところは1)


以上がビット演算の流れです。
Pythonではビット反転をするときはXORを使って反転するしかなさそうです。
知っていればハマりませんが、思い込むとなかなか抜けられなくて苦労しました。

今回は以上です。

2012/10/01 追記
せっかくなので、負値を二の補数表現に変換するプログラムも記述しておきます。
-3600という値を二の補数表現にします。


>>> p = -3600
>>> (-p ^ 0xFFFF) + 1
61936


これで上記の二の補数表現と同じになりました。

テーマ : プログラミング
ジャンル : コンピュータ

Python:PILをWindows7 64bit環境で使う

こんにちは。もう9月だというのにまだまだ暑いですね。

 今回はPythonを使用していてハマったエラーの対処法を載せておきます。
Pythonにおいて画像を処理しよとするとよく用いられるのが、PIL(Python Imaging Library )です。

[参考]Python Imaging Library (PIL) : http://www.pythonware.com/products/pil/

このライブラリを使うと簡単に画像処理ができます。
具体的にはPNG画像を表示するためにPILを使用したいと考えました。
しかし、ライブラリをインストール後以下の様なエラーメッセージが表示され、正常に動作しません。

ImportError: The _imaging C module is not installed

モジュールをインストールしたはずなのに見つからないようです。
*インストールはインストーラではなく手動で行いました
このエラーメッセージを頼りに検索していくと、Windowsの64bit環境において起きるということがわかりました。

[参考]流れ着いたら。。。:http://www.flotsam-fareast.com/2011/02/64bit-windows-python-image-library-20110212.html

そこで、以下のサイトから64bit用のPILのインストーラをダウンロードしてインストールしました。

Unofficial Windows Binaries for Python Extension Packages:http://www.lfd.uci.edu/~gohlke/pythonlibs/

しかし、インストラーを起動すると以下の様なメッセージが表示され、それ以上進めなくなりました。
Python version 2.* is required, which was not found in the registry
PILを手動でインストールしなければその時点で発生したエラーだと思います。
そこで対処法を調べると、レジストリを読み間違えているということがわかりました。
[参考]Yamada Program:http://yamada-program.blogspot.jp/2011/05/pythonsetuptools-64bit.html

ただし、私はPythonのレジストリを書き換えたくないという事情があり、他の方法を模索することとしました。

Unofficial Windows Binaries for Python Extension PackagesでダウンロードしたPILはインストールできないので、EXEファイルをExplzhで解凍して問題のあるDLLを直接置き換えることとしました。

まず、Python Imaging Library (PIL)からPython Imaging Library 1.1.7 Source Kitをダウンロードし、解凍します。
次にUnofficial Windows Binaries for Python Extension Packagesから自分のPython環境に合致するインストーラをダウンロードします。
ダウンロードしたインストーラをExplzhで解凍します。
展開すると中には、以下の二つのフォルダがあります。

・PLATLIB
・SCRIPTS

まず、PLATLIBの中のPILというフォルダの中身をすべて、Imaging-1.1.7>PILに上書きします。
次にSCRIPTSの中身をすべて、Imaging-1.1.7>Scriptsに上書きします。

最後にImaging-1.1.7のフォルダをPython26\Lib\site-packagesなどに移し、PYTHONPATHを通せば完了です。
PYTHONPATHの通し方は、前の記事を参照して下さい。

これでレジストリを書き換えることなくWindows7 64bit環境でPILが使用出来るようになりました。
今回は以上となります。

テーマ : プログラミング
ジャンル : コンピュータ

Python:super()の謎エラー

こんばんは。最近健康面に不安を感じ、大学近くのジムに通い始めました。
大学に入る前より15キロ太ったので、なんとかそのときの体重に戻したいです。

 さて、最近Pythonにはまっております。
[参考]日本Pythonユーザ会 :http://www.python.jp/Zope
Pythonは非常に開発がやりやすいうえ、WindowsだろうがLinuxだろうが同じコードで動いてくれるのが研究でも趣味でも役に立ちます。
特にお気に入りなのは、対話型シェルを使用して一行ずつプログラムを書ける点です。
これを使えば、使い方の分からないメソッドをその場でテストしたり、自作関数の動作テストも容易に出来ます。
 また豊富な機能を実現するモジュールが数多く存在するのが素晴らしいです。
例としてTkinterというGUI製作用のモジュールが存在します。
[参考]Tkinter 8.4 reference: a GUI for Python :http://infohost.nmt.edu/tcc/help/pubs/tkinter/
PythonをWindowsにインストールしたときに標準でついてくるIDLEは、Tkinterで製作されているようです。
Tkinterの使い方は日本語のサイトはいつかあるようですが、紫藤さんのWebページを参考にさせていただきました。
[参考]紫藤のページ :http://www.shido.info/py/index.html

 今回はそのときに真っ先にハマった内容を備忘録を兼ねて書きます。
参考にしたサンプルの内容としてはWidgetを配置する簡単なものです。
その際の初期化を再現すると以下の様になります。


class Son(Parent):
    def __init__(self):
        Parent.Frame.__init__(self)



直接、親クラスの初期化メソッドを呼んでいました。
しかし、Python(2.x系列)では、


super(クラス名, self).メソッド(…)


と書けば親クラスのメソッドを呼べるのに、なぜそうしないのか気になりました。
そこで、実際にsuperを使用して記述しなおしました。


class Son(Parent):
    def __init__(self):
        super(Son, self).__init__()


これを実行すると、以下のようなエラーが出ました
TypeError: super() argument 1 must be type, not classobj
検索してみると、結構困っている人が多いようですが、なんとか以下のような記述を発見しました。
"the problem is that you are using old-style python classes, which do not support super. The easy way to fix this is to put object at the base of your inheritance tree. "
[参考]Open Source Applications Foundation :http://chandlerproject.org/Projects/UsingSuper
どうもクラスのスタイルが古いらしいです。
最初の例題通りのやり方で回避できるようですが、クラスのスタイルが古いとはどういうことでしょうか。
もう少し調べると、hope-echoesさんのwebページを参考にして答えが出ました。
[参考]大カフェイン :http://d.hatena.ne.jp/hope-echoes/20080409/1207732499
Objectクラスを親にもつクラスは全て新形式のクラスで、持たないものは旧形式のクラスのようです。
type()で調べると

・新形式


>>> type(datetime.datetime)
<type 'type'>


・旧形式


>>> type(Tkinter.Frame)
<type 'classobj'>


となりました。
ここでtypeが'classobj'になるものは旧形式のクラスのようです。
つまりTkinterのFrameは旧形式のクラスなので、super()のサーポート外だったようです。

 これでsuper()でエラーが出る理由と回避方法がわかりました。
Pythonはやりはじめなので、今後もこのようなエラーにハマると思いますが、がんばります。
今回は以上で終わりです。

テーマ : ホビーロボット
ジャンル : コンピュータ

月別アーカイブ
カテゴリ
FC2カウンター
最新コメント
リンク
最新トラックバック
検索フォーム
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。