忍者ブログ
  • 2019.11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 2020.01
javascriptのflatMapとpythonの内包表記
javaでflatMapを覚えてから奇妙だなと思っていた。
これって何に使うのだろうかと。

結論から言うと直積を求めたいときに使うのである。

もし、組み合わせを求めたい場合、どのように求めるだろうか。

■pythonソース
teams = range(5)
[(x, y) for xi, x in enumerate(teams) for yi, y in enumerate(teams) if xi < yi]
■python結果
[(0, 1),
 (0, 2),
 (0, 3),
 (0, 4),
 (1, 2),
 (1, 3),
 (1, 4),
 (2, 3),
 (2, 4),
 (3, 4)]

実はこれと同じことをflatMapでも行える。
■javascriptソース
range = (x)=>function*(){ for(var i = 0;i<x;i++) {yield i;}};
teams = range(5);
Array.from([[]])
.flatMap(x=>Array.from(teams()).map(y=>x.concat(y)))
.flatMap((x, xi)=>Array.from(teams()).filter((y,yi)=>xi<yi).map(y=>x.concat(y)))
■javascript結果
(10) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
0: (2) [0, 1]
1: (2) [0, 2]
2: (2) [0, 3]
3: (2) [0, 4]
4: (2) [1, 2]
5: (2) [1, 3]
6: (2) [1, 4]
7: (2) [2, 3]
8: (2) [2, 4]
9: (2) [3, 4]
length: 10
__proto__: Array(0)
おもしろいなあ。
PR
【2019/06/16 18:19 】 | Python | 有り難いご意見(0)
                                    
超万能なsorted
Pythonでの不満。Python2にあったsorted関数のcmpがなくなって、keyになった。
なぜ、cmpはなくなったのだろうか?考えてみた。

まず、sortedへの不満として、複数キーの昇順・降順ができなくなった。というものがあった。
誤りである。
どうやらkeyにタプルを返すと勝手に複数キーの昇順としてソートしてくれるようだ。
つまり、文字は反転。数字はマイナスにすることで、それらしきものができる。
c=[('a', 1), ('a', 2), ('b', 2), ('b', 1)]
sorted(c, key=lambda x: (tuple(map(lambda z:(0xff-z), x[0].encode("cp932"))), -x[1]))
[('b', 2), ('b', 1), ('a', 2), ('a', 1)]
ここで気づいた。この比較用キーの作成はcmpの場合、ソート方法に依存してしまう。O(2*NlogN)の頻度で比較用キーが作成されてしまうのだ。
この点、key指定だと比較用キーはO(N)のみの作成となる。
すばらしい

ただし、文字列の降順としては可変長の場合、前述の方法は使えない。なので、classを作ってみた。
class Keys:
    def __init__(self, v, isAscs):
        self.v = v
        self.isAscs = tuple(isAscs)

    def __lt__(self, other):
        for i, s, isAsc, o in zip(range(len(self.isAscs)-1, -1, -1), self.v, self.isAscs, other.v):
            lt = [lambda p1, p2: p1 > p2, lambda p1, p2: p1 < p2][isAsc]
            ret = lt(s, o)
            if ret or i and lt(o, s):
                break
        return ret

    @staticmethod
    def of(isAscs, keymap=lambda x:x):
        return lambda item: Keys(keymap(item), isAscs)


if __name__ == "__main__":
    arr = [("a", 2), ("b", 1), ("a", 1), ("b", 2)]
    print(arr)
    #1項目め降順、2項目め昇順
    print(sorted(arr, key=Keys.of((False, True))))
    #1項目め2文字目昇順、1項目め1文字目昇順
    print(sorted(arr, key=Keys.of((True, False), keymap=lambda x:(x[0][1], x[0][0]))))
うん、素晴らしい。
【2019/05/02 08:43 】 | Python | 有り難いご意見(0)
                                    
Where dose Python have a member at?

Pythonでフィールドを定義するときに他言語と合わせて クラスブロックに入れてみた場合とコンストラクタに入れてみた場合を比較してみた。

i = 0

def func():
    global i
    i = i + 1
    return i
    
class Person:
    vals1 = func() #field define

    def __init__(self):
        print '[Person.__init__]'
        self.vals2 = func() #costruct

print "finished compile."

func()

info = Person()

print info.vals1, info.vals2

del info

info = Person()

print info.vals1, info.vals2
結果
finished compile.
[Person.__init__]
1 3
[Person.__init__]
1 4

どうやらクラスブロックにフィールドを指定したら、コンパイル時に プリプロセスされてしまってスカラーに変換されてるっぽい。
コンストラクターに宣言するのが正しそうだ。

【2015/01/10 07:47 】 | Python | 有り難いご意見(0)
                                    
PythonのWriting for Definition

Pythonの変数のスコープについてなぜグローバル変数を用いるためにglobalをつける必要があるか考察してみた。

まず、C言語の関数から見てみよう

int func()
{
    int L;
    L = 23;
    printf("%d%s", L, G); //出力:"23bit"
}

C言語において、変数は「Use with definition」である。
この関数を見て分かることは変数Lがローカルで宣言されているため、ローカル変数であり、変数Gはローカルではないということである。

次に、VBの関数を見てみよう。

Sub func
    L = 23
    print L & G ’出力:"23bit"
End Sub

VBにおいて、Option Explicitをつけない場合、変数は「Use without definition」である。
この関数をみて分かる事はLはローカル変数かもしれないし、グローバル変数かもしれない。
(グローバル変数として動いた気はするけども、参照が他になければローカル変数と変わらない)
Gは確実にグローバル変数であるということである。
なぜなら、G="bit"であり他所で確実に設定されているためである。
これを逆説的に言うと、関数内を見渡して未設定で参照のみの変数が使われている場合、ローカル変数では有りえない。ということである。

いよいよPythonの関数を見てみよう

def func():
    L = 23
    print L,G #出力:"23bit"

Pythonにおいて、変数は「Use with definition. But writing is definition.」である。
なんとなく、CとVBの両方の経験者は「Use without definition」と捕らえてしまいがちであるが、よくよくググってみても変数を宣言しなくても使えると書いているサイトは見当たらない。

関数内を見渡して、Lはここで値を設定しているのでローカル変数であり
Gは値を設定していないのでローカル変数ではない。
もっと言えば、VBにおいて、Gがローカル変数ではない理由は動かすか、グローバル変数宣言部を見るかしないと分からない。

しかし、Pythonの場合、関数func内をみるだけで完結する。
このように、ローカル変数が未設定で参照のみが行われることはないという特徴をグローバル変数と見做すというのは非常に上手いやりかたに思える。

実際に変数Gには何が設定されているのか知りたければGで検索すれば設定場所がひっかかる。

def func2():
    global G
    G = "bit"

global変数に値を設定する場合、ローカル変数の「値を設定して使う」というルールに参加させるため、globalキーワードを用いる。
これで、どれだけグローバル変数Gが多くの箇所で使われていようが設定している箇所をすべて見つけることができるのである。

なぜ、こんな仕様になったのか考えてみると、システム屋ではない人が作ってもPythonは整った文になるように設計されているということである。
意外と素人に多いコーディングは、めんどくさいから取り敢えずローカル変数をグローバル変数に 持っていくというものである。一番ひどい場合、ループ変数さえも持っていくのである。
しかし、グローバル変数にループ変数を宣言したところでそれを使うのがめんどくさいのがPythonの特徴である。
ローカル変数宣言の1行を省略できるのにglobalを付けてグローバルのループ変数をわざわざ宣言して使う人は少ないだろう。

さらに次のルールが生まれる。

◎1ソースであれば、グローバル変数名で検索して見つかった箇所が全て関数内でのみ、かつglobalキーワードが使われていない場合、グローバル変数は未使用である。

◎globalキーワード付変数を使わない関数を、他のソースに流用した場合において、ローカル変数名とグローバル変数名がたまたま一致したために、ローカル変数への代入がグローバル変数の更新に繋がることはない。

とてもよく考えられているルールではないだろうか?

【2014/12/27 08:45 】 | Python | 有り難いご意見(0)
                                    
| ホーム |