Python 言語の理解 その4

今時の仕様 なの⁈

先日、複数行文字列を使ったコメントの書き方が面白いなと思いましたが、数値や文字列の操作も なかなか興味深いです(笑)。

僕はかなり昔にC言語を覚えただけで、それからは他の言語はほとんど習得してなかったからなんでしょうかねぇ。なんだか便利な感じを受けます。
これは今時の仕様なんでしょうかね。

 

進数表示と進数記述について

・10進数の10を 2進数で表示

 >>> bin(10)
 '0b1010'

・10進数の10を 8進数で表示
 >>> oct(10)
 '0o12'

・10進数の10を 16進数で表示
 >>> hex(10)
 '0xa'

・2進数の1010を 10進数で表示
 >>> 0b1010
 10

・8進数の12を 10進数で表示
 >>> 0o12
 10

・16進数のaを 10進数で表示
 >>> 0xa
 10

これらは、ありがちな事かもしれません。

 

変数の型表示はこのようにするとできるようです。以下整数の例。

>>> age = 10
>>> type (age)
<class 'int'>

 

これはプログラムで判定できるのか?そんな使い道はないか(笑)でも試すと、

>>> type (age) == "<class 'int'>"
False

➡できない!一致しない!

 

>>> type(age) == type(age)
True

➡これはできてる!

>>> type(age) == type(1)
True

➡もしやるなら、こちらかな

 

二重の比較判定が同時にできる⁈

>>> age = 10
>>> 5<age and age<20
True

これをまとめてこんな書き方ができる!これは超便利
>>> 5<age<20
True

 

複数行の文字列の書き方1

>>> poem1="""やま
... かぜ
... れんこん
... """
>>> poem1
'やま\nかぜ\nれんこん\n'

 

複数行の文字列の書き方2

>>> poem2="やま\nかぜ\nれんこん\n"
>>> poem2
'やま\nかぜ\nれんこん\n'

 

文字列の追加

数値の ⁺= はC言語でも使えるけど文字列には無かったような・・・

>>> poem2
'やま\nかぜ\nれんこん\n'
>>> poem2 += "いちご"
>>> poem2
'やま\nかぜ\nれんこん\nいちご'

 

文字列の繰り返しも出来る!

>>> moji = "うまい"
>>> moji * 3
'うまいうまいうまい'

>>> moji3 = "うまい" * 3
>>> moji3
'うまいうまいうまい'

 

文字列の部分取り出し

>>> id1 = "abcdefghijklmn"
>>> id2 = "ABCDEFGHIJKLMN"
>>> id1
'abcdefghijklmn'
>>> id2
'ABCDEFGHIJKLMN'

 

文字列から3文字目の取り出し
>>> id1[2]
'c'
>>> id2[2]
'C'
>>> id1[6]
'g'
>>> id2[6]
'G'

半角も全角も同じ添え字で可能みたいです!これは凄い!

 

7文字目から4文字目まで・・逆方向に指定するとなにも取り出せない

>>> id1[6:3]
''

 

7文字目から10文字目までを取り出す。

>>> id1[6:9]
'ghi'

解りやすいように、+3 と取り出す文字数を指定するとよいかも。

>>> id1[6:6+3]
'ghi'

 

全角でもやり方は同じ。
>>> id2[6:6+3]
'GHI'

 

6文字目から最後まで

>>> id1[5:]
'fghijklmn'

>>> id2[5:]
'FGHIJKLMN'
 

先頭から4文字目まで
>>> id1[:3]
'abc'
>>> id2[:3]
'ABC'

 

先頭から4文字目まで1文字おきに
>>> id1[:3:2]
'ac'
>>> id2[:3:2]
'AC'

 

頭から1文字おきに取り出すならこうなる。
>>> id1[::2]
'acegikm'
>>> id2[::2]
'ACEGIKM'

 

4文字目から1文字おきに取り出す、これは面白いかも。
>>> id1[3::2]
'dfhjln'
>>> id2[3::2]
'DFHJLN'

 

最後から逆順に取り出す。こんなことが出来るの?
>>> id1[::-1]
'nmlkjihgfedcba'
>>> id2[::-1]
'NMLKJIHGFEDCBA'

 

文字列の一部を置換することはできない。これは不便。

>>> id1
'abcdefghijklmn'
>>> id1[3]
'd'

4文字目は d でした。それを s に置換してみる
>>> id1[3]="s"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

 

文字なのでシングルクオートで括ってみたが結果は同じ。
>>> id1[3]='s'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

前半と、後半を取り出して合成するとできなくはないけど。。

>>> id1 = id1[:2] + 's' + id1[4:]

 

そのやり方は以下に書いてありました。

 

# 文字列からリストへ変換し、4文字目を置換
>>> str_list = list(id1)
>>> str_list[3] = 's'

# リストから文字列へ戻す
>>> id1 = "".join(str_list)
>>> print(id1)

'abcsefghijklmn'

 

出来てる!

最後のリストから文字列へ戻すやり方の "". これはどういう意味?

そこを外すとどうなるか

 

>>> id1=join(str_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'join' is not defined

 

なぜ怒られているのか理解できない。(笑)
それも外すと。。。

>>> id1=str_list
>>> id1
['a', 'b', 'c', 's', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']

 

なにがなんだか(;^ω^)

Python 言語の理解 その3

サンプルプログラムなどで一番便利に使うのは画面への文字出力じゃないかな。

Pythonでも多言語にありがちな print です。ですが、そのオプションに驚きが!

基本はかなり普通です。

 

print ( 値1,値2,値3,・・・)

 

驚きは以下のような不思議なオプション。

print ( 値1,値2,値3,・・・,sep="区切り文字",end="行末文字")

 

値の間の区切りに使う文字、改行に使う文字を指定することが出来ます。
なんだか不思議です。

C言語のように、もっと簡単に書式設定ができればいいのに(笑)

Python 言語の理解 その2

Python 言語では 行末に ; を書いたりする必要はないようです。

改行までが 行です。見たまんま。

逆に2行にまたがるような時は、物理的に改行する手前に \ を入れるようです。

例えば

 

abc = 1 + 2 + 3 \

+ 4 + 5

 

この逆で、1行に複数のステートメントを書くときは ; で区切るらしいです。

 

abc = 1 + 2 + 3 ; cba = 4 + 5

 

左から解釈されていくようなので次のようにも書けます。

 

abc = 1 + 2 + 3 ; cba = abc + 4 + 5

 

普通かな(笑)

 

Python 言語の理解 その1

不思議なコメント

 

#で始める文章は行末までコメント扱い。

これは一般的な他の言語と似ているような気がします。

ですが、面白いのはコレ

""" で始める文章は """ が出てくるまでコメント扱い。

ダブルコーテーションを三つ続けて書くと、再びダブルコーテーションが三つ続けて現れるまでが 複数行の文字列として扱われ、意味のない文字列は無視される為、コメントとして利用できるようです。なんか変(笑) /* ~ */ みたいな使い方なんですね。

 

 

Python 言語の理解

LEDのチカチカや、スイッチのパチパチは、書籍通りにやれば制御できたので(笑)、今度は言語そのもの Python3についていろいろ勉強して理解しようと思います。

今までの書籍にも Python3については触れてはいいるものの、あくまで制御のためのサンプルプログラムなので、Python3について全般的な事は置きざりになっているはずです。これから長い付き合いをしていく為に本格的に Python3で遊ぶ気になってきたので専門書を買ってみました。

「詳細!Python3入門ノート」大重美幸著 初版 第3刷

f:id:osadamao:20180213224203j:plain

 この本の中で、Python3のコーディングをタイプするならAtomというエディタが便利、と書かれており、linux版もあるようなのですが、Raspbian で使えるようにカスタマイズされたものは見つけられませんでした。(>_<)

 なので、気にせず今まで通りのスタイルで入力していく事にしました。

言語についてはココに要約を書き出していく事は止めて、古いC言語などを知っている僕が、「おや?」っと思ったことだけを書き出していこうと思っています。

 

 

Iceweaselのインストール

標準のブラウザ「Chromium」よりも使い慣れたFirefox互換の「iceweasel」を入れてみました。

 

pi@raspberrypi:~ $ sudo apt-get install iceweasel iceweasel-l10n-ja
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
firefox-esr firefox-esr-l10n-ja libjsoncpp1
提案パッケージ:
fonts-stix | otf-stix fonts-lmodern mozplugger
以下のパッケージが新たにインストールされます:
firefox-esr firefox-esr-l10n-ja iceweasel iceweasel-l10n-ja libjsoncpp1
アップグレード: 0 個、新規インストール: 5 個、削除: 0 個、保留: 0 個。
42.6 MB のアーカイブを取得する必要があります。
この操作後に追加で 94.7 MB のディスク容量が消費されます。
続行しますか? [Y/n] Y
取得:1 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libjsoncpp1 armhf 1.7.4-3 [66.2 kB]
取得:2 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf firefox-esr armhf 52.6.0esr-1~deb9u1 [41.7 MB]
取得:3 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf firefox-esr-l10n-ja all 52.6.0esr-1~deb9u1 [564 kB]
取得:4 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf iceweasel all 52.6.0esr-1~deb9u1 [122 kB]
取得:5 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf iceweasel-l10n-ja all 1:52.6.0esr-1~deb9u1 [120 kB]
42.6 MB を 1分 51秒 で取得しました (383 kB/s)
以前に未選択のパッケージ libjsoncpp1:armhf を選択しています。
(データベースを読み込んでいます ... 現在 126542 個のファイルとディレクトリがインストールされています。)
.../libjsoncpp1_1.7.4-3_armhf.deb を展開する準備をしています ...
libjsoncpp1:armhf (1.7.4-3) を展開しています...
以前に未選択のパッケージ firefox-esr を選択しています。
.../firefox-esr_52.6.0esr-1~deb9u1_armhf.deb を展開する準備をしています ...
'firefox-esr による /usr/bin/firefox から /usr/bin/firefox.real への退避 (divert)' を追加しています
firefox-esr (52.6.0esr-1~deb9u1) を展開しています...
以前に未選択のパッケージ firefox-esr-l10n-ja を選択しています。
.../firefox-esr-l10n-ja_52.6.0esr-1~deb9u1_all.deb を展開する準備をしています ...
firefox-esr-l10n-ja (52.6.0esr-1~deb9u1) を展開しています...
以前に未選択のパッケージ iceweasel を選択しています。
.../iceweasel_52.6.0esr-1~deb9u1_all.deb を展開する準備をしています ...
iceweasel (52.6.0esr-1~deb9u1) を展開しています...
以前に未選択のパッケージ iceweasel-l10n-ja を選択しています。
.../iceweasel-l10n-ja_1%3a52.6.0esr-1~deb9u1_all.deb を展開する準備をしています ...
iceweasel-l10n-ja (1:52.6.0esr-1~deb9u1) を展開しています...
mime-support (3.60) のトリガを処理しています ...
desktop-file-utils (0.23-1) のトリガを処理しています ...
libc-bin (2.24-11+deb9u1) のトリガを処理しています ...
man-db (2.7.6.1-2) のトリガを処理しています ...
gnome-menus (3.13.3-9) のトリガを処理しています ...
hicolor-icon-theme (0.15-1) のトリガを処理しています ...
libjsoncpp1:armhf (1.7.4-3) を設定しています ...
firefox-esr (52.6.0esr-1~deb9u1) を設定しています ...
firefox-esr-l10n-ja (52.6.0esr-1~deb9u1) を設定しています ...
iceweasel (52.6.0esr-1~deb9u1) を設定しています ...
iceweasel-l10n-ja (1:52.6.0esr-1~deb9u1) を設定しています ...
libc-bin (2.24-11+deb9u1) のトリガを処理しています ...
pi@raspberrypi:~ $

 

これでインストールは完了です。

 

f:id:osadamao:20180212223408p:plain


メニューに追加されたFirefoxESRを起動するとFirefox初回起動時の設定インポート確認が表示されました。

 

f:id:osadamao:20180212215044p:plain

とりあえずインポートしておく。

f:id:osadamao:20180212215106p:plain

 これまた初回起動時に確認されるGoogleアカウント

 

f:id:osadamao:20180212215157p:plain

 無事画面が出ました。 

f:id:osadamao:20180212215220p:plain

 操作は慣れ親しんだものなので使いやすいですが、遅いです。

Raspbianに標準でインストールされているChromiumは、RaspberryPiのリソースに合わせてチューニングされているのでしょうか。

どちらをメインに使うかは、これから使いながら考えていくことにしたいです。

 

 

Raspberry Pi3 GPIO 制御2

先のブログにも書いたように参考にする書籍によって使用しているGPIO制御モジュールが2種類あります。

"RPi.GPIO" と "wiringpi" 

その2つの違いは何なんでしょうか。

以前に買った書籍「電子部品ごとの制御を学べる!RaspberryPi電子工作」だと "wiringpi" が使用されており、Raspberry Pi に Raspbian をインストールすればwiringpi も含まれており何もしなくても使える、という旨の事が書いてありますが、書籍の中に紹介されているサンプルプログラムをそのまま入力して実行させてみると、この様なエラーになりました。

 

>>> %Run Raspberry_Pi3_GPIO_wiringpi.py

Traceback (most recent call last):
File "/home/pi/soc/Raspberry_Pi3_GPIO_wiringpi.py", line 4, in <module>
import wiringpi as GPIO
ImportError: No module named 'wiringpi'

 

'wiringpi'が見つからない旨のエラーメッセージなので、 綴り誤りだと思って何度も確認しましたがあっているようです(笑)
ならば、という事で'wiringpi'をインストールしてみました。

 

pi@raspberrypi:~ $ pip3 search wiringpi
ledDriver (1.0) - Python LED light strip and PWM drivers using the
WiringPi2 library.
wiringpi (2.44.4) - A python interface to WiringPi 2.0 library which allows
for easily interfacing with the GPIO pins of the
Raspberry Pi. Also supports i2c and SPI.
wiringpi2 (2.32.3) - A python interface to WiringPi 2.0 library which allows
for easily interfacing with the GPIO pins of the
Raspberry Pi. Also supports i2c and SPI

 

wiringpiとwiringpi2の違いは何?全く同じ説明が書かれてます。
違いが判りませんが版数の新しいほう wiringpi を入れてみることにしました。


pi@raspberrypi:~ $ pip3 install wiringpi
Collecting wiringpi
Downloading wiringpi-2.44.4-cp35-cp35m-linux_armv7l.whl (256kB)
100% |████████████| 266kB 803kB/s Installing collected packages: wiringpi
Successfully installed wiringpi-2.44.4
pi@raspberrypi:~ $

 

インストールは難なく成功したようなので、LEDを点灯させてみます。
5秒点灯して消灯させます。

★まずはRPi.GPIOを使う例

#Raspberry Pi3 GPIO 出力1RPi.GPIOを使う実験
#ライブラリの読み込み
import RPi.GPIO as GPIO
from time import sleep
LED_PIN = 23

#初期化
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#出力モード設定
GPIO.setup (LED_PIN,GPIO.OUT,initial = GPIO.LOW)

#出力設定
GPIO.output (LED_PIN,GPIO.HIGH)
sleep(5)
GPIO.output (LED_PIN,GPIO.LOW)

#GPIOリセット終了
GPIO.cleanup()

 

★つぎはwiringpiを使う例

#Raspberry Pi3 GPIO 出力1wiringpiを使う実験
#ライブラリの読み込み
import wiringpi as GPIO
from time import sleep
LED_PIN = 23

#初期化
GPIO.wiringPiSetupGpio()


#出力モード設定
GPIO.pinMode (LED_PIN,GPIO.OUTPUT)

#出力設定
GPIO.digitalWrite (LED_PIN,GPIO.HIGH)
sleep(5)
GPIO.digitalWrite (LED_PIN,GPIO.LOW)

 

どちらも、ほぼ同じなのですが初期化の部分で wiringpi には、GPIO番号指定なのか物理位置番号指定なのかを宣言することや、.setwarnings のようなワーニングメッセージを抑止するようなものがありません。また、wiringpi では終るときに明確にGPIOを開放する指定が無いような気がします。それらを考えると、初心者なら wiringpi を使うよりRPi.GPIOを使った方が安全なような気がします。

 

PWMで疑似アナログ出力する場合での RPi.GPIOを使う場合とwiringpiを使う場合の違いを確認してみました。

★まずはRPi.GPIOを使う例

#Raspberry Pi3 GPIO PWM 出力 RPi.GPIOを使う実験

#ライブラリの読み込み
import RPi.GPIO as GPIO
from time import sleep

LED_PIN = 23

#初期化
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#出力モード設定
GPIO.setup (LED_PIN,GPIO.OUT,initial = GPIO.LOW)

#出力設定
p2 = GPIO.PWM(LED_PIN,200)
p2.start(0)

try:
    while True:
        for dc2 in range(0,101,10):
            p2.ChangeDutyCycle(dc2)
            print(dc2)
            sleep(0.3)

#例外処理
except KeyboardInterrupt:
    print ( 'CTRL + C' )
    pass

p2.stop()

#GPIOリセット終了
GPIO.cleanup()

 

★続いてwiringpiを使う例

#Raspberry Pi3 GPIO PWM 出力 wiringpiを使う実験

#ライブラリの読み込み
import wiringpi as GPIO
from time import sleep

LED_PIN = 23

#初期化
GPIO.wiringPiSetupGpio()


#出力モード設定
GPIO.pinMode (LED_PIN,GPIO.OUTPUT)

#出力設定
GPIO.softPwmCreate (LED_PIN,0,100)

try:
    while True:
        for dc2 in range(0,101,10):
            GPIO.softPwmWrite(LED_PIN,dc2)
            print(dc2)
            sleep(0.3)

#例外処理
except KeyboardInterrupt:
    print ( 'CTRL + C' )
    pass 

 

疑似アナログ出力をするケースでも RPi.GPIOを使う場合とwiringpiを使う場合の違いは、デジタル出力のケースと同じでした。

つまり あえて"wiringpi"を使った方がいい理由は僕にはわかりませんでした。

 

という事で定番のRPi.GPIOを使ってLEDを順番につけてみるスクリプトを作ってみました。

#Raspberry Pi3 GPIO 出力

#ライブラリの読み込み
import RPi.GPIO as GPIO
from time import sleep

 

#初期化
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

 

#出力モード設定
for LED_PIN in [23,24,25,16,20,21]:
GPIO.setup (LED_PIN,GPIO.OUT,initial = GPIO.LOW)

 

#出力設定
try:
    while True:
        for LED_PIN in [23,24,25,16,20,21]:
            GPIO.output (LED_PIN,GPIO.HIGH)
            sleep(0.1)
            GPIO.output (LED_PIN,GPIO.LOW)

        sleep(0.1)

        for lp in range(3):
            for LED_PIN in [23,24,25,16,20,21]:
                GPIO.output (LED_PIN,GPIO.HIGH)

            sleep(0.1)

            for LED_PIN in [23,24,25,16,20,21]:
                GPIO.output (LED_PIN,GPIO.LOW)

            sleep(0.1)

except KeyboardInterrupt:
    print ( 'CTRL + C' )
    pass

 

#GPIOリセット終了
GPIO.cleanup()

 

f:id:osadamao:20180211142818j:plain

 

 

 

LEDの点灯制御についてはうまくできるようになったので、今度はスイッチのON、OFFを読み出すようなプログラムも整理しました。

 

#Raspberry Pi3 GPIO 入力1
#ライブラリの読み込み
import RPi.GPIO as GPIO
from time import sleep

SW_PIN = 4

#初期化
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#GPIO4を入力モードとして設定
GPIO.setup (SW_PIN,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)

#コントロールCが押されるまでループ

try:
    while True:
        if GPIO.input(SW_PIN) == GPIO.HIGH : #GPIO.LOW または GPIO.HIGHを得る
            print ( 'SW on:GPIO' + str(SW_PIN) + ' HIGH' )
        else :
            print ( 'SW off:GPIO' + str(SW_PIN) + ' LOW' )

        sleep (1)

#例外
except KeyboardInterrupt :
    print ( 'CTRL + C' )
    pass


#GPIOのリセット終了
GPIO.cleanup()

 

 

 

 

参考にさせていただいたサイト

ag.hatenablog.com