変数はraw stringが使えない(涙)

7月 22nd, 2017

正規表現で「?」にマッチさせようとして躓いた。

普通、改行の「\n」のように「\」を前につければ行けるはず。でも、「\?」では上手く行かない。

結論から言えば、これは「\\?」にすると動く。pythonのための「\」と正規表現のための「\」の両方がいるらしい。

これを避ける方法として、raw stringなるものがあるのだそう。

m=re.compile(‘\\?’)
とするところを
m=re.compile(r’\?’)

この程度なら、大差は無いが、もっとややこしい指定の時、頭に「r」をつけておくと「\」をたくさん書かなくて良くなる。もちろん、見やすくなる。

ただ、私の場合、パターンは、予め変数に入っている。ファイルから読み込んで予めまとめてコンパイルしておく方式なので、直に書けない。

こんな感じ。
pat=’\?’
m=re.compile(pat)

これ、一体どうやって頭に「r」をつければいいんだ???pat=’r'+’\?’とかもやってみたけど駄目だった。

調べて見たら、変数にはraw stringは使えないらしい。そ、そーか・・・reptを使うのだそう。repr(pat)で、patの中身がraw stringになる。

例えば、str=’test\n’の場合、そのままprintすると「test」と表示され、改行される。

だが、print (repr(str))にすると、「\n」は、書いてあるそのままのものとして、「test\n」が表示される。

残念ながら、正規表現のパターンには使えなかった。良く分からないが、上手く反応しない…まあいいや。「\」を少し余分に書くだけだ。うん。

クラス内で関数(メソッド)にlistを投げると怪しきことに?

7月 13th, 2017

なんというか・・・、これは、pythonのバージョンによって挙動が変わる可能性がある。私のは3.4なので、それ以前だと多分発生するけど、以降だとちょっと分からない。

何のことを言っているか、意味不明なので、プログラムに語ってもらいやしょう。

#coding:UTF-8

class Test:
    def moto(self):
        a=10
        self.add(a)
        print ('a=',a)

    def add(self,num):
        num+=10
        print ('num=',num)

class LTest:
    def moto(self):
        alist=['林檎','みかん']
        self.ladd(alist)
        print ('alist=',alist)

    def ladd(self,data):
        st='すいか'
        data.append(st)
        print ('data=',data)

t=Test()
t.moto()
t2=LTest()
t2.moto()

初めのクラス「Test」は、数値の代入実験。aの値を同じクラス内の別の関数に送って別途計算。結果は
num=20
a=10
これはまあ、分かる。

問題はLTestクラスの方。予想では、
alist=['林檎','みかん']
data=['林檎','みかん','すいか']

となるかと思いきや、実際は、
alist=['林檎','みかん','すいか']
data=['林檎','みかん','すいか']

書き換えた覚えの無い「alist」まで書き換わってる~。\(^O^)/。頼んでないぞーう。

ちなみに、dataとして受け取って、そのまま扱っているのが悪いかもしれない、と、下記のように一旦別の変数に投入してから操作しても無駄。

    def ladd(self,ldata):
        data=ldata
        st='すいか'
        data.append(st)
        print ('data=',data)

何故こうなるかは、薄々分かる気はするのだが、ちょっと自信がない。とりあえず、気をつけましょう、ということで~。

すとんと胸に落ちた話

7月 8th, 2017

久々にプログラミング以外のネタ。

ネットをうろうろしていて見つけた、この話がなかなかどうして、すごく面白かった。

小林麻央報道の「印象操作」にザワつく乳がん女子の胸の内

小林麻央さんの報道に胸を痛めつつ、どこか消しがたい違和感を抱いていた。それが、上記ブログを読んで、得心がいった。報道での扱い方が、ひどく偏っている気がして、それが気になっていたのだな、と。

特に3ページ目の「生きてる人の闘病記って売れないんだよね」と出版社の人から言われたという話は、当事者ならぬ私もショックだった。いや、でも、だって、重要なのは、生きる方の話じゃない?私が当事者だったら、絶対そうだ。絆を深め、治療の甲斐もなく死にました、という話より、どんな治療をして、どんな選択肢があって、何を悩み、何を迷い、どうやって生き延びたのか、どんな問題が起こるのか、どう解決したのか(あるいはしなかったのか)、そこを知りたい。

書籍も出していらっしゃるそうで。詳しくはそちら、かな?

松 さや香 著
『彼女失格 恋してるだとか、ガンだとか』幻冬舎(2013)

桁区切りがある数値

6月 14th, 2017

ユーザーの数値入力を受け付けると、桁区切りが入ってしまっている場合がある。

例えば「1800」は「1,800」と入力されるかもしれない。

。。。パイソン君にどう思う(?)か聞いてみた。

a=’1,800′
str(a)

絶対無理だろうと思ったらやっぱり駄目だった。「変なの入ってる」と言われた。

まあ、そうだよね。次は・・・

a=1,800

苦情を言われるかと思いきや、何故かすんなり通ってしまった。「何だと思った」のか聞いてみた。

答え:タプルでしょ。1と800。

言われて見ればそれもそうだな。やっぱり先に「,」を取り除かないと駄目っぽい。

a=’1,800′
b=int(a.replace(‘,’,”))

これでbに1800という数値が入りました。めでたしめでたし。

・・・とは行かないのがチャットボットの悲しいところ。やみくもに「,」を取ってしまうと、意図しない動作をしかねない。数字の間の「,」限定だと少しましだけど、でも、例えば「1,13,5」(1と13と5)という意味で入力している場合もある。

人間にフレンドリーな設定でプログラムを書こうと思うと、こういう細かい手間がすごく多くて疲れる・・・ユーザーに「数値の場合は桁区切りを使わないで」もしくは「数字の桁区切り以外で、数字を列挙したい時は『,』ではなく『、』を使って」とかやっちゃえばプログラムは簡単になる。でもそれじゃ、チャットボットの値打ちがないと思うんだなぁ・・・

三桁ごとの「,」を外す、という手もあるんだけど、でも「1と800」という意味で「1,800」と入力している場合に問題が起こる。

人間は、その数字が出てくるコンテキスト(背景)から瞬時に判断するけど、コンテキスト理解をプログラムで実行するのは、難易度が高すぎる(多分今もっとも進歩したAIでも、この辺りはまだ全然足りていないはず)。まあ、人間もたまに読み間違うけど。

次善の策で、場面限定で「,」を外すようにすれば、まあそれほど誤作動せずにすむかな・・・

ちなみに、逆に桁区切りを挿入する場合は、下記らしい。

‘{:,}’.format(1234567890)

これで1,234,567,890が得られる。

いたずらしてみた。

‘{:;}’.format(1234567890)

桁区切り指定をセミコロンに。叱られた。

「intに;を使うなんて聞いてない」

ごめん。数値と良く使う記号ならいいかも、と「-」指定にしてみた。

‘{:-}’.format(1234567890)

まんま1234567890が返ってきた。

そうか・・・。formatについて少し調べて見たけど、ちょっと難しくて良く分からない。もうしばらく眺める必要がありそう。

datetimeで日付、時刻を扱う

6月 13th, 2017

あまりにも何回も同じことを検索するので・・・自分用メモ。

now=datetime.datetime.today()

とした時の年、月、日、時間、分、秒、マイクロセカンドの取り出し
now.year
now.day
now.hour
now.minute
now.second
now.microsecond

型はint。

now自体の型はdatetime.datetime。

nowの中身(例):
2017-06-13 11:27:11.178127

フォーマットして出力したい場合
%Y..年、%m..月、%d..日、%H..時、%M..分、%S..秒
例:)now.strftime(“%Y年%m月%d日 %H時%M分%S秒”)

フォーマット後の型はstr。

フォーマット時に使われる「%Y」等の詳細は、下記参照

http://docs.python.jp/3.6/library/datetime.html

str→datetimeにしたい時
teststr=’2017/01/01 20:29:39′
datetime.datetime.strptime(teststr, “%Y/%m/%d %H:%M:%S”)

とりあえず、いじょ。

割り算で商と余りを同時に得る

6月 2nd, 2017

忘れそうなので、取り急ぎここにメモ。

Pythonで割り算は「/」か「//」。

「//」を使うと小数点以下切り捨て。

余りを得るには「%」

うう、ちょっと間違えそう・・・「%」で割り算する言語もあったような・・・

それはそれとして、割り算の商と余りを同時に得る方法もある。それがdivmod。

例えば、75割る60なら、下記のようになる。

divmod(75,60)

すると、答えは、

(1,15)

1余り15。

これを使う時はこんな感じ。

h,m=divmod(75,60)

これでh=1、m=15が入る。

いじょ。

正規表現で特定文字列を含まない方法

5月 29th, 2017

正規表現を相変わらず勉強中。

まあまあ慣れてきたのだが、困ったのが「特定文字列を含まない」ケースを一体どうするのか。特定「文字」を含まない、なら「^」が使える。でも文字列だと上手く行かない。

例えば、「ユーザー名変更」や「ユーザー名を変更」にはヒットして欲しいが、「ユーザー名を変更しない」は外して欲しい。

「(?!××)」というのがどうやらそうらしい、というので試してみた。

こんな感じ。

ユーザー名.*変更.*(?!ない)

でも、上手く行かない。他を更に調べたら、「(?!.*Value).*」みたいなのを使えとあった。Valueには外したい文字列が入る。

というわけで、改めて変更。

ユーザー名.*変更.*(?!.*ない).*

・・・やっぱり上手く行かない。ひょっとして、と()の前の「.*」を外してみた。

ユーザー名.*変更(?!.*ない).*

これで無事動いた。でも、尻尾の「.*」は、私の場合、不要な気がする。文中の一部について外したい場合用なのではないかと推定。で、更にこれも外してみた。

ユーザー名.*変更(?!.*ない)

やはりこれでも動く。いまいち理屈は分からないが(こらこら)、とりあえず動いたからいいことにしよう(こうやって誤解したまま進んでしまうんだよなあ・・・)。

タイマーを止められない

5月 27th, 2017

タイマーを実装したまでは良かった・・・が。

実際に使ってみると、「タイマーを開始したけど止めたいゾ」ということがままある。

というわけで、止める方法を探したのだが・・・

このタイマーは、「threading」を使って別スレッドを走らせている。

じゃ、別スレッド止めるか破棄すればいいじゃん。

そう単純に考えていた。

ところが。

「現状では、優先度 (priority)やスレッドグループがなく、スレッドの破壊 (destroy)、中断 (stop)、一時停止 (suspend)、復帰 (resume)、割り込み (interrupt) は行えません。」(Python 3.6.1ドキュメントより)

うそん・・・

あの手この手でなんとかしようともがいてみた。threading.timerを使うのではなく、単にカウントにしておいて、キーボードからの入力によって反応するようにとか。

上記手法は、一回目は上手く行ったけど、一回しかやらせてもらえなかった。まあ、スレッドの破壊・復帰はできませーん、とあるんだからそうなんだけど。「run()」は一回しか呼び出せない仕様なのだ。うう。

1秒ごとに信号チェックをして動作して行けば、見た目的にはきちんと動いているように見えるはずだけど…

大体っ、そもそもっ、inputがいつまででも入力待ちでぼけーっとしているのが悪い(←八つ当たり)。

後は、別個のプログラムにして操作、くらいかなあ…しかしpythonのプログラムから別プログラムへ信号を送る方法が分からない。ファイルに書き込めば、データを受け渡しできるけど…別プログラムは、1秒ごとにそれをチェックして、合図を取り込む。できれば直でやりとりしたいところ。

…何かとっても危険な香りがする。まあWebのチャットcgiいじった時は、アクセスするたびに毎回ファイルを開いちゃ読み、開いちゃ読みしてたけど。

python機能の限界に時々頭がぶつかるようになった今日この頃。でも、そこをなんとかできないのは、私の能力が低いからなんだよな…うう。やりたいことは単純なんだから、何か道があるに違いない・・・

lstripやrstripの罠(単なる勘違いともいう)

5月 26th, 2017

文字列操作をおさらいしていて、変な事例に出くわした。

—-
st=’python’
print (st.lstrip(‘typ’))
—-

これの実行結果はどうなるか。

そのままpythonになる、と思っていた。が、これは間違い。「hon」が表示される。

あれれれれ~?????えーとえーとえーと。

print (st.lstrip(‘pyt’))

なら、「hon」が返るのは分かるけど。

そう、根本的に、勘違いしていた。lstripやrstrip、stripは、フレーズに反応しているのではなく、「文字」に反応するコマンドなのだ。つまり、「typ」と「pyt」は、lstrip等々にとっては同じ意味で、とにかく「tとyとp」。順序はどーでもいい。

知らなかったよ~~~~~。初歩の文字列操作なのに。がーんがーんがーん。

で、どう動いているかというと、lstrip(‘typ’)の場合、左から文字列をチェックして、

1.tかyかpがあれば、削除
2.tでもyでもpでもなければ、処理終了

ひーーー。間違えてた。かんっぺきに間違えてた。恐ろしや。rstripは右からチェック、stripは両方からチェック。ほえ~~~。

なので、行末の「\n」を削るのに「rstrip(‘\n’)」は、文字列途中の「\n」を削る心配はないにせよ、末尾に特殊な入力をすると、おかしなことになる可能性がなきにしもあらず、ということに…

むむむ。とりあえず、まあ、いい、ことにしようかな(本当にいいのか?)

正規表現vs類語辞書 補足

5月 26th, 2017

同じネタで引っ張ってるなあと思いつつ…

試行回数を5万回に増やしてみた。

結果は、コンパイルを活用しても、結局正規表現を使わない方が早かった。

なので、正規表現を使わなくても行けるケースでは、原則、正規表現を使わずやる方がいいっぽい。

他方、例えばメールの中からメルアドと電話番号を取り出すとか、Webアドレスを取り出すとか、そういう場合は、正規表現を使わないとなかなか難しい(やってやれなくはなさそうだが)。

後、出現順序にこだわる場合も正規表現を使った方がやりやすそうではある…