網頁

2015年7月23日 星期四

[vim] display trailing white space

in vim

:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$/                

2015年7月17日 星期五

[data base] mariadb install for python

Env:

Ubuntu 14.10
python 2.7


Commands:

import MySQLdb needs
apt-get install python2.7-mysqldb

import mysql.connector as mariadb needs
http://dev.mysql.com/downloads/connector/python/

2015年7月15日 星期三

[vimdiff] diffg

在vimdiff下我們可以用好用的diffg來同步

當我們用vimdiff時左右兩邊視窗不一致時,我們可以在左邊視窗用 "大寫V" 選擇要左右sync的區塊,然後再按下 :diffg ,就會把右邊視窗所選的同步到左邊。

如果是按下 :diffget,就會把左邊同步到右邊。

NOTE: 通常不額外設定 git difftool 使用的也是vimdiff。

2015年7月13日 星期一

[opencv] install

主題: opencv install


很難安裝, 筆記一下

Ubuntu 14.10

- pre install QT4

apt-get install qt4-default libqt4-dev qtchooser qt4-designer

- git clone opencv

git clone https://github.com/Itseez/opencv.git

cd opencv
mkdir release
cd release

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..

sudo make
sudo make install

成功

MAC OS Yosemite 10.10.4

直接brew install opencv會有問題

- 一樣要先裝QT, 但要brew要多下"build-from-source"的option

brew install qt --build-from-source

- git clone opencv(這邊就和上面一樣)

失敗... 

2015年7月9日 星期四

[Python] hook function for self.x, self.x = 3, delete self.x

主題: hook function for self.x, self.x = 3, delete self.x


說明:

我們有一個class A,
假設我們想要在"讀取"self.x或在"設定"self.x時或在"刪除"self.x時可以多做一些"額外的事情(某個function)",那麼該怎麼把我們的function插入呢?

實作:

實作一個descriptor, 並安裝到A中成為class member data。

#!/usr/bin/python

class Integer(object):
        def __init__(self, name):
                self.name = name

        def __get__(self, instance, cls):
                if instance is None:
                        return self
                else:
                        return instance.__dict__[self.name]

        def __set__(self, instance, value):
                if not isinstance(value, int):
                        raise TypeError('Expected an int')
                instance.__dict__[self.name] = value

        def __delete__(self, instance):
                del instance.__dict__[self.name]

class A(object):
        x = Integer('x')
        def __init__(self, x, y):
                self.x = x
                self.y = y

a = A(1.0, 2)

結果:

Traceback (most recent call last):
  File "./descriptor.py", line 27, in 
    a = A(1.0, 2)
  File "./descriptor.py", line 24, in __init__
    self.x = x
  File "./descriptor.py", line 15, in __set__
    raise TypeError('Expected an int')
TypeError: Expected an int

無效: 

因為這件事情很重要,再重複一次,
"實作一個descriptor, 並安裝到A中成為class member data。"
如果你實作了一個descriptor,但安裝到class中不是成為class member data而是instance data, 這樣是不起作用的。

class A(object):
        def __init__(self, x, y):
                self.x = Integer('x')
                self.y = y

繼承還是有效: 

class B(A):
        def __init__(self, x, y):
                self.x = x
                self.y = y

b = B(1.0, 2)
繼承還是有效,因為child class繼承了class member data
Traceback (most recent call last):
  File "./descriptor.py", line 32, in 
    b = B(1.0, 2)
  File "./descriptor.py", line 29, in __init__
    self.x = x
  File "./descriptor.py", line 15, in __set__
    raise TypeError('Expected an int')
TypeError: Expected an int

順帶一題: 

property, classmethod, staticmethod, __slots__都是相同概念:
安裝一個descriptor到class上

2015年7月8日 星期三

[linux] add user

主題: 假設想要多個可信認的user共用一台機器,每個user有權限可以轉換身分到root


How to ?

1. 加入一般身分的user
2. 修改visudo

2015年7月6日 星期一

[Python] @staticmethod 和 @classmethod

主題: @staticmethod和@classmethod的差別

說明:

這兩個都是decorator,
一言以蔽之 classmethod的input function第一個參數必須是class,
而staticmethod則第一個參數就是真的參數。

可以參考這邊(staticmethod/classmethod)

另外一提,這兩個的實作方式和@property的做法很像。

[Python] __slots__ 記憶體優化工具

主題: __slots__

範例:



不使用__slots__優化記憶體(內部為一個hash table)
#!/usr/bin/python
from pympler import asizeof

class A(object):
        #__slots__ = ['year', 'month', 'day']
        def __init__(self, year, month, day):
                self.year = year
                self.month = month
                self.day = day

a = A(1,2,3)
print asizeof.asized(a, detail=1).format()
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f15e50e9cd0="" data-blogger-escaped-at="" data-blogger-escaped-object=""> size=552 flat=64
    __dict__ size=488 flat=280
    __class__ size=0 flat=0
使用__slots__優化記憶體(不存table, 分開以更節省記憶體的方式存)
#!/usr/bin/python
from pympler import asizeof

class A(object):
        __slots__ = ['year', 'month', 'day']
        def __init__(self, year, month, day):
                self.year = year
                self.month = month
                self.day = day

a = A(1,2,3)
print asizeof.asized(a, detail=1).format()
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x191f6c8="" data-blogger-escaped-at="" data-blogger-escaped-object=""> size=224 flat=72
    __slots__ size=80 flat=80
    month size=24 flat=24
    day size=24 flat=24
    year size=24 flat=24
    __class__ size=0 flat=0

結論:

使用__slots__優化記憶體 552->224
缺點就是因為內部不存hash table, 所以你也只能使用__slots__指定的那些屬性名稱

2015年7月5日 星期日

[Python] property繼承的寫法

主題: property繼承的寫法


假設我們有一個擁有name property的class A:

class A(object):
        def __init__(self):
                print ("A init")
        @property
        def name(self):
                print ("A name getter")
        @name.setter
        def name(self, x):
                print ("A name setter")
我們想要對A的name property繼承,並且改寫。 改寫的方式想要繼承A原本的一些code再附加新的class的一些code,可以這樣寫:
class B(A):
        def __init__(self):
                print ("B init")

        @property
        def name(self):
                super(B, B).name.fget(self)
                print ("B name getter")

        @name.setter
        def name(self, x):
                super(B, B).name.fset(self, x)
                print ("B name setter")

或者把fget和fset換成__get__和__set__
class B(A):
        def __init__(self):
                print ("B init")

        @property
        def name(self):
                super(B, B).name.__get__(self)
                print ("B name getter")

        @name.setter
        def name(self, x):
                super(B, B).name.__set__(self, x)
                print ("B name setter")

為什麼可以這樣? 有興趣的人可以去研究一下 property這個class

還有一點要注意, 其實這樣的寫法是"定義B的自己版本name property", 換句話說,
B.name和A.name是兩個不同的版本。
也就是如果B只有定義getter或是setter,那麼這個property也只會剩下getter或是setter的能力:


#!/usr/bin/python

class A(object):
        def __init__(self):
                print ("A init")
        @property
        def name(self):
                print ("A name getter")
        @name.setter
        def name(self, x):
                print ("A name setter")


class B(A):
        def __init__(self):
                print ("B init")

        @property
        def name(self):
                super(B, B).name.__get__(self)
                print ("B name getter")

b = B()
b.name
b.name = 3

結果:
B init
A name getter
B name getter
Traceback (most recent call last):
  File "./property.py", line 25, in 
    b.name = 3
AttributeError: can't set attribute

Shell 已返回1

結論:

1. child class要改寫parent class的property最好全部都改寫,除非你知道你在做什麼,你真的想閹割parent class的setter or getter or deleter ?
2. child class若要呼叫parent class的class method(memer data), 那就要用 super(B, B).name的寫法
3. property class有實作"descriptor protocol"(__get__, __set__, __delete__這三個function),
property class的__get__會去呼叫 property class的instance method: fget
property class的__set__會去呼叫 property class的instance method: fset
property class的__delete__會去呼叫 property class的instance method: fdel

2015年7月4日 星期六

[Python] decorator的等價寫法

主題: decorator的等價寫法


class A(object):
    @property
    def func(self):
       ...



class A(object):
    def func(self):
       ...
    func = property(func)

換句話說這時候 func經過property之後
1. 從單純的func變成為property
2. func則變為 class variable (不是intance variable)


[Python] property and descriptor protocol

主題: 了解property的概念

簡介: 

假設今天我們有一個需求,我們有一個A class:
a = A()
當寫 a.m 我們希望呼叫到 A.f
當寫 a.m = 3我們希望呼叫到 A.g
當寫 del a.m我們希望呼叫到A.p

那我們該如何實作 ?

答案在這邊 (直接參考property這個class的實作方式)

個人理解:

先說一下規則好了,如果一個有實作 "descriptor protocol"的class,假設叫D好了:
當寫 
d = D()
d  
d = 5
del d
則會觸發
__get__
__set__
__del__

據此,我們可以讓 __get__ 去呼叫A.f
__set__去呼叫A.g
__del__去呼叫A.p
就可以達到題目需求....

但這樣很不彈性,
因此我們再多寫三個function以便有機會可以替換掉
A.f
A.g
A.p

其實以上就是property的概念:
"
Property是一個class擁有fget, fset, fdel這三個function,
我們可以用 getter, setter, deleter去註冊這三個function,
且getter, setter, deleter回傳都是Proptery object。
"

2015年7月2日 星期四

[Python] 雙底線的用處

目的: 了解雙底線的用處

1. 不可繼承
2. public
3. 不管是class member或method都遵循這個規則

以下用class method舉例:
#!/usr/bin/python

class A(object):
        def __init__(self):
                pass

        def test1(self):
                print "test1"
        def __test2(self):
                print "test2"

class B(A):
        def __init__(self):
                pass

b = B()
b.test1()
b.__test2()
結果:(注意test1有印出來但呼叫__test2時發生AttributeError的Exception)
test1
Traceback (most recent call last):
  File "./private.py", line 18, in 
    b.__test2()
AttributeError: 'B' object has no attribute '__test2'

[Python] old style class vs new style class

目的: 了解什麼是old style class ? 什麼是 new style class ? 如何使用super ?


先看這篇 ,簡短的說明一下這篇內容好了:
1. class有繼承object這個class是new style class, 否則就是 old style class
2. old style class是for python 2.2以前的向下相容
3. python內建的繼承功能可以說是由 object class所提供

其中有一點很重要,就是super()功能是new style class的功能。

正規上如果B要繼承A且建構順序是先A再B, 我們就要用super()
super()的影響在多重繼承上會很明顯。
可以看這篇 

總結一下:
1. super()的用法是: 第一個參數是這個class名稱, 第二個參數是self
2. 執行順序有一套自己的演算法,可以想成parent class的__init__一定先執行:
#!/usr/bin/python

class A(object):
        def __init__(self):
                print ("[A]")

class A0(A):
        def __init__(self):
                super(A0, self).__init__()
                print ("[A0]")

class A1(A):
        def __init__(self):
                super(A1, self).__init__()
                print ("[A1]")

class A2(A):
        def __init__(self):
                super(A2, self).__init__()
                print ("[A2]")

class A21(A2):
        def __init__(self):
                super(A21, self).__init__()
                print ("[A21]")

class A22(A2):
        def __init__(self):
                super(A22, self).__init__()
                print ("[A22]")

class B(A1, A21, A22, A0):
        def __init__(self):
                super(B, self).__init__()

B()
結果: (所有class的__init__都被剛好執行一次, 且有parent/child繼承關係parent一定會比child先做)

[A]
[A0]
[A2]
[A22]
[A21]
[A1]

2015年7月1日 星期三

[Python][cook][269-269] with 語法

目的: 了解Python with語法

Python with的語法有點像是c++的scope,當進入with區間時, 會進入__enter__function, 當離開with區間時, 會先執行__exit__ function (即使with區間產生exception也會進__exit__)

範例1. __enter__ return自己


#!/usr/bin/python

class A:
        def __init__(self):
                print "__init__"

        def __enter__(self):
                print "__enter__"
                return self

        def __exit__(self, exc_ty, exc_val, tb):
                print "__exit__"

a = A()
with a:
        print " in with "

結果:

__init__
__enter__
 in with x=<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7faa8553ac68="" data-blogger-escaped-at="" data-blogger-escaped-instance="">
__exit__

範例2. __enter__ 不return值

#!/usr/bin/python
class A:
        def __init__(self):
                print "__init__"

        def __enter__(self):
                print "__enter__"

        def __exit__(self, exc_ty, exc_val, tb):
                print "__exit__"

a = A()
with a as x:
        print " in with x=%r" % x

結果:

__init__
__enter__
 in with x=None
__exit__

範例3. __enter__ return另一個class的obj


#!/usr/bin/python
#!/usr/bin/python
class B:
        def __init__(self):
                pass

        def showB(self):
                print "This is B"

class A:
        def __init__(self):
                print "__init__"

        def __enter__(self):
                print "__enter__"
                return B()

        def __exit__(self, exc_ty, exc_val, tb):
                print "__exit__"

a = A()
with a as b:
        print " in with "
        b.showB()

結果:

__init__
__enter__
 in with
This is B
__exit__

範例4. with區間有raise Exception

#!/usr/bin/python
class A:
        def __init__(self):
                print "__init__"

        def __enter__(self):
                print "__enter__"
                return self

        def __exit__(self, exc_ty, exc_val, tb):
                print "__exit__ %r %r %r" % (exc_ty, exc_val, tb)

a = A()
with a as x:
        print " in with x=%r" % x
        raise Exception("exp1234")

結果: (可以看到__exit__仍有被執行且__exit__的參數有exception相關資訊)

__init__
__enter__
 in with x=<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f1c4bc0ac68="" data-blogger-escaped-at="" data-blogger-escaped-instance="">
__exit__  Exception('exp1234',) 
Traceback (most recent call last):
  File "./with.py", line 16, in 
    raise Exception("exp1234")
Exception: exp1234

[Python][Cook][265-266] 實作class 的 __str__, __repr__ 的效果

目的: 觀察實作__str__, __repr__的效果

實作前:

#!/usr/bin/python



class A:

        def __init__(self, x, y):

                self.x = x

                self.y = y



a = A(5, 6)

print a

print "%r" % a

print "{0!r}".format(a)

print str(a)

<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f433e42db48="" data-blogger-escaped-at="" data-blogger-escaped-instance="">
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f433e42db48="" data-blogger-escaped-at="" data-blogger-escaped-instance="">
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f433e42db48="" data-blogger-escaped-at="" data-blogger-escaped-instance="">
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f433e42db48="" data-blogger-escaped-at="" data-blogger-escaped-instance="">

實作後:

#!/usr/bin/python



class A:

        def __init__(self, x, y):

                self.x = x

                self.y = y

        def __str__(self):

                return 'This is A __str__'

        def __repr__(self):

                return '<A __repr__>'



a = A(5, 6)

print a

print "%r" % a

print "{0!r}".format(a)

print "{0!s}".format(a)

print str(a)

This is A __str__
<A __repr__>
<A __repr__>
This is A __str__
This is A __str__