Sharing

2011年12月13日 星期二

SCST 使用方式


收集了一些還不錯的連結

http://wiki.alpinelinux.org/w/index.php?title=High_performance_SCST_iSCSI_Target_on_Linux_software_Raid&oldid=4999
介紹用 RAID 和 SCST 的搭配使用,不過後半段很清楚的描述從無到有把 iSCSI Target export 出去的流程


Add Target
-add_target -driver
Open Device
-open_dev -handler -attributes   這裡是填 handler 的屬性
Add LUN
-add_lun -driver -target [-group ] -device -attributes
Enable Target
-enable_target -driver
Enable Driver
-set_drv_attr iscsi -attributes enabled=1
Disable Driver
-set_drv_attr iscsi -attributes enabled=0
Disable Target
-disable_target -driver
Remove LUN
-rem_lun -driver -target [-group ]
Close Device
-close_dev -handler
Remove Target
-rem_target -driver


整個流程 Sample

# 加一個 Target
pjack@ubuntu3371:~$ sudo scstadmin -add_target iqn.2011-12.org.pjack:foo1 -driver iscsi

Collecting current configuration: done.


-> Making requested changes.
        -> Creating target 'iqn.2011-12.org.pjack:foo1' for driver 'iscsi': done.
        -> Done.

All done.


# 列出所有的 target 或是列出屬於 iscsi driver 的 Target, 看有沒有出現剛剛新增的
pjack@ubuntu3371:~$ sudo scstadmin -list_target

Collecting current configuration: done.

        Driver Target
        --------------------------------
        iscsi iqn.2011-12.org.pjack:foo1

All done.

pjack@ubuntu3371:~$ sudo scstadmin -list_driver iscsi

Collecting current configuration: done.

        Driver Target
        --------------------------------
        iscsi iqn.2011-12.org.pjack:foo1

All done.



# 看一下這個 Target 的一些屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_tgt_attr iqn.2011-12.org.pjack:foo1 -driver iscsi -nonkey

Collecting current configuration: done.

        Attribute                    Value                                                                       Writable      KEY
        --------------------------------------------------------------------------------------------------------------------------
        HeaderDigest                 None                                                                        Yes           No
        RspTimeout                   90                                                                          Yes           No
        InitialR2T                   No                                                                          Yes           No
        MaxBurstLength               1048576                                                                     Yes           No
        QueuedCommands               32                                                                          Yes           No
        MaxRecvDataSegmentLength     1048576                                                                     Yes           No
        tid                          2                                                                           No            No
        redirect                     < not set="">                                                                   Yes           No
        NopInTimeout                 30                                                                          Yes           No
        rel_tgt_id                   0                                                                           Yes           No
        NopInInterval                30                                                                          Yes           No
        ImmediateData                Yes                                                                         Yes           No
        MaxXmitDataSegmentLength     1048576                                                                     Yes           No
        cpu_mask                     ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff     Yes           No
        enabled                      0                                                                           Yes           No
        per_portal_acl               0                                                                           Yes           No
        addr_method                  PERIPHERAL                                                                  Yes           No
        FirstBurstLength             1048576                                                                     Yes           No
        MaxSessions                  0                                                                           Yes           No
        MaxOutstandingR2T            32                                                                          Yes           No
        DataDigest                   None                                                                        Yes           No
        comment                      < n a="">                                                                       Yes           No
        io_grouping_type             auto                                                                        Yes           No

        Dynamic attributes available
        ----------------------------
        allowed_portal
        OutgoingUser
        IncomingUser

        LUN CREATE attributes available
        -------------------------------
        read_only



# 新增一個 Device
pjack@ubuntu3371:~$ sudo scstadmin -open_dev disk01 -handler vdisk_blockio -attributes filename=/dev/rbd0

Collecting current configuration: done.


-> Making requested changes.
        -> Opening device 'disk01' using handler 'vdisk_blockio': done.
        -> Done.

All done.


# 列出所有的 Device
pjack@ubuntu3371:~$ sudo scstadmin -list_device

Collecting current configuration: done.

        Handler           Device
        ------------------------
        vdisk_nullio     -
        vdisk_fileio     -
        vdisk_blockio    disk01
        vcdrom           -

All done.

# 列出使用 vdisk_blockio handler 的 Device
pjack@ubuntu3371:~$ sudo scstadmin -list_handler vdisk_blockio

Collecting current configuration: done.

        Handler           Device
        ------------------------
        vdisk_blockio    disk01

All done.


# 列出這個 device 的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_dev_attr disk01 -nonkey

Collecting current configuration: done.

        Attribute             Value                                          Writable      KEY
        --------------------------------------------------------------------------------------
        usn                   27cddc71                                       Yes           No
        blocksize             512                                            No            No
        t10_dev_id            27cddc71-disk01                                Yes           No
        rotational            1                                              No            No
        nv_cache              0                                              No            No
        type_string           Direct-access device (e.g., magnetic disk)     No            No
        removable             0                                              No            No
        read_only             0                                              No            No
        resync_size           < n a="">                                      Yes           No
        threads_num           1                                              Yes           No
        size_mb               1024                                           No            No
        write_through         0                                              No            No
        thin_provisioned      0                                              No            No
        handler               vdisk_blockio                                  No            No
        filename              /dev/rbd0                                      Yes           Yes
        dump_prs              < n a="">                                      Yes           No
        exported              < n a="">                                      No            No
        threads_pool_type     per_initiator                                  Yes           No
        type                  0                                              No            No


# 新增一個 LUN
pjack@ubuntu3371:~$ sudo scstadmin -add_lun 0 -driver iscsi -target iqn.2011-12.org.pjack:foo1 -device disk01

Collecting current configuration: done.


-> Making requested changes.
        -> Adding device 'disk01' at LUN 0 to driver/target 'iscsi/iqn.2011-12.org.pjack:foo1': done.
        -> Driver/target is not a fibre channel target, ignoring.
        -> Done.

All done.

# 透過 list_target 再多加 driver 參數, 可以看到這個 target 的 LUN
pjack@ubuntu3371:~$ sudo scstadmin -list_target iqn.2011-12.org.pjack:foo1 -driver iscsi

Collecting current configuration: done.

Driver: iscsi
Target: iqn.2011-12.org.pjack:foo1

Assigned LUNs:

        LUN  Device
        -----------
        0    disk01


All done.

# 看 LUN 的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_lun_attr 0 -driver iscsi -target iqn.2011-12.org.pjack:foo1 -nonkey

Collecting current configuration: done.

        Attribute     Value      Writable      KEY
        ------------------------------------------
        read_only     0          No            No
        device        disk01     No            No

All done.


# Enable Target
pjack@ubuntu3371:~$ sudo scstadmin -enable_target iqn.2011-12.org.pjack:foo1 -driver iscsi

Collecting current configuration: done.


-> Making requested changes.
        -> Enabling driver/target 'iscsi/iqn.2011-12.org.pjack:foo1': done.
        -> Done.

All done.

# 多了一個 rel_tgt_id 的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_tgt_attr iqn.2011-12.org.pjack:foo1 -driver iscsi

Collecting current configuration: done.

        Attribute      Value     Writable      KEY
        ------------------------------------------
        rel_tgt_id     1         Yes           Yes

        Dynamic attributes available
        ----------------------------
        allowed_portal
        OutgoingUser
        IncomingUser

        LUN CREATE attributes available
        -------------------------------
        read_only

All done.

# 把 iscsi enable
pjack@ubuntu3371:~$ sudo scstadmin -set_drv_attr iscsi -attributes enabled=1 -noprompt

Collecting current configuration: done.


-> Making requested changes.
        -> Enabling driver 'iscsi': done.
        -> Done, 0 change(s) made.

All done.

# 從另一台看是否能找到
pjack@ubuntu64-33-7:~$ sudo iscsiadm -m discovery -t st -p 172.16.33.71
172.16.33.71:3260,1 iqn.2011-12.org.pjack:foo1

# Login
pjack@ubuntu64-33-7:~/Git/WiStor/Node/src/wistor/ext/itri/iscsi$ sudo iscsiadm -m node -T iqn.2011-12.org.pjack:foo1 -p 172.16.33.71 -l
Logging in to [iface: default, target: iqn.2011-12.org.pjack:foo1, portal: 172.16.33.71,3260]
Login to [iface: default, target: iqn.2011-12.org.pjack:foo1, portal: 172.16.33.71,3260]: successful


# 回到本機看一下連線 session
pjack@ubuntu3371:~$ sudo scstadmin -list_sessions

Collecting current configuration: done.

Driver/Target: iscsi/iqn.2011-12.org.pjack:foo1

        Session: iqn.1993-08.org.debian:01:4e712cd57f99

        Attribute                    Value                                      Writable      KEY
        -----------------------------------------------------------------------------------------
        write_cmd_count              0                                          Yes           No
        HeaderDigest                 None                                       Yes           No
        sid                          10000023d0200                              Yes           No
        read_cmd_count               118                                        Yes           No
        bidi_io_count_kb             0                                          Yes           No
        commands                     0                                          Yes           No
        InitialR2T                   No                                         Yes           No
        MaxBurstLength               1048576                                    Yes           No
        MaxRecvDataSegmentLength     1048576                                    Yes           No
        active_commands              0                                          Yes           No
        none_cmd_count               7                                          Yes           No
        unknown_cmd_count            0                                          Yes           No
        ImmediateData                Yes                                        Yes           No
        MaxXmitDataSegmentLength     262144                                     Yes           No
        reinstating                  0                                          Yes           No
        FirstBurstLength             262144                                     Yes           No
        read_io_count_kb             354                                        Yes           No
        MaxOutstandingR2T            1                                          Yes           No
        bidi_cmd_count               0                                          Yes           No
        write_io_count_kb            0                                          Yes           No
        DataDigest                   None                                       Yes           No
        initiator_name               iqn.1993-08.org.debian:01:4e712cd57f99     Yes           No
        force_close                                                        Yes           No

# Logout
pjack@ubuntu64-33-7:~/Git/WiStor/Node/src/wistor/ext/itri/iscsi$ sudo iscsiadm -m node -T iqn.2011-12.org.pjack:foo1 -p 172.16.33.71 -u
Logging out of session [sid: 2, target: iqn.2011-12.org.pjack:foo1, portal: 172.16.33.71,3260]
Logout of [sid: 2, target: iqn.2011-12.org.pjack:foo1, portal: 172.16.33.71,3260]: successful

# disable target
pjack@ubuntu3371:~$ sudo scstadmin -disable_target iqn.2011-12.org.pjack:foo1 -driver iscsi -noprompt

Collecting current configuration: done.


-> Making requested changes.
        -> Disabling driver/target 'iscsi/iqn.2011-12.org.pjack:foo1': done.
        -> Done.

All done.

# remove lun
pjack@ubuntu3371:~$ sudo scstadmin -rem_lun 0 -driver iscsi -target iqn.2011-12.org.pjack:foo1 -device disk01 -noprompt

Collecting current configuration: done.


-> Making requested changes.
        -> Removing LUN 0 from driver/target 'iscsi/iqn.2011-12.org.pjack:foo1': done.
        -> Driver/target is not a fibre channel target, ignoring.
        -> Done.

All done.


# close the device
pjack@ubuntu3371:~$ sudo scstadmin -close_dev disk01 -handler vdisk_blockio -noprompt

Collecting current configuration: done.


-> Making requested changes.
        -> Closing device 'disk01' using handler 'vdisk_blockio': done.
        -> Driver/target is not a fibre channel target, ignoring.
        -> Driver/target is not a fibre channel target, ignoring.
        -> Done.

All done.

# remove the target
pjack@ubuntu3371:~$ sudo scstadmin -rem_target iqn.2011-12.org.pjack:foo1 -driver iscsi -noprompt

Collecting current configuration: done.


-> Making requested changes.
        -> Removing virtual target 'iqn.2011-12.org.pjack:foo1' from driver 'iscsi': done.
        -> Driver/target is not a fibre channel target, ignoring.
        -> Done.

All done.



http://iscsi-scst.sourceforge.net/SCST_Gentoo_HOWTO.txt
這篇裡面有不少設定 scstadmin 的範例

這篇大部份不透過 scstadmin 設定

這篇是滿早期的文章,有些已經不適用,包括安裝的 ppa 不能用,其它的部份則是可參考



這應該是把 scst 寫的最詳細的資料,而且有很多專有名詞的解釋及用法,改天應該要好好研究一下。
裡面有提到 /sys/kernel/scst_tgt/ 裡面的目錄結構,如果要查看每一個 target 有那一些連線,就要查看這個目錄,
/sys/kernel/scst_tgt/targets/iscsi//sessions

這是 scstadmin 官方的 README


https://git.ipxe.org/mirror/scst/.git/blob/master:/scstadmin/scstadmin.sysfs/scstadmin
這份有整理好的 scstadmin 指令


General Operations
-write_config < file>
Writes the current configuration to < file>.
-clear_config
Clear all SCST configuration.
Query Operations
-list_handler
List all available handlers
-list_handler [< hndlr>]
List all available device under specific handler
-list_driver
List all available drivers
-list_driver [< driver>]
List all available target under specific driver
-list_target
List all available targets
-list_target [< target>][-driver < driver>]
List all available LUN under specific target
List Attribute Operations
-list_scst_attr
List all attributes for SCST
-list_hnd_attr < hndlr>
List all attributes for a given handler.
-list_dev_attr < device>
List all attributes for a given device.
-list_drv_attr < driver>
List all attributes for a given driver.
-list_lun_attr < lun> -driver < driver> -target < target> [-group < group>]
List all attributes for a driver/target/lun
-list_sessions
List all current initiator sessions


# 看一下有支援那些 handler
pjack@ubuntu3371:~$ sudo scstadmin -list_handler

Collecting current configuration: done.

        Handler
        -------------
        vdisk_fileio
        vdisk_blockio
        vdisk_nullio
        vcdrom

All done.

# 看一下有支援那些 driver
pjack@ubuntu3371:~$ sudo scstadmin -list_driver

Collecting current configuration: done.

        Driver
        -----
        iscsi

All done.

# 看一下有 blockio 支援的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_hnd_attr vdisk_blockio -nonkey

Collecting current configuration: done.

        Attribute       Value                                          Writable      KEY
        --------------------------------------------------------------------------------
        type_string     Direct-access device (e.g., magnetic disk)     No            No
        disk01          < n a="">                                      Yes           No
        trace_level     out_of_mem                                     Yes           No
                        minor                                          Yes           No
                        pid                                            Yes           No
                        line                                           Yes           No
                        function                                       Yes           No
                        special                                        Yes           No
                        mgmt                                           Yes           No
                        mgmt_dbg                                       Yes           No
        type            0                                              No            No

        Possible trace levels:
          (use trace_level="add < level>", none, all or default to set):
                debug, function, line, pid, entryexit,
                buff, mem, sg, out_of_mem, special,
                scsi, mgmt, minor, mgmt_dbg, scsi_serializing,
                retry, recv_bot, send_bot, recv_top, pr,
                send_top, order,

        Device CREATE attributes available
        ----------------------------------
        blocksize
        write_through
        rotational
        nv_cache
        thin_provisioned
        filename
        removable
        read_only

# 看一下有 fileio 支援的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_hnd_attr vdisk_fileio -nonkey

Collecting current configuration: done.

        Attribute       Value                                          Writable      KEY
        --------------------------------------------------------------------------------
        type_string     Direct-access device (e.g., magnetic disk)     No            No
        trace_level     out_of_mem                                     Yes           No
                        minor                                          Yes           No
                        pid                                            Yes           No
                        line                                           Yes           No
                        function                                       Yes           No
                        special                                        Yes           No
                        mgmt                                           Yes           No
                        mgmt_dbg                                       Yes           No
        type            0                                              No            No

        Possible trace levels:
          (use trace_level="add < level>", none, all or default to set):
                debug, function, line, pid, entryexit,
                buff, mem, sg, out_of_mem, special,
                scsi, mgmt, minor, mgmt_dbg, scsi_serializing,
                retry, recv_bot, send_bot, recv_top, pr,
                send_top, order,

        Device CREATE attributes available
        ----------------------------------
        o_direct
        blocksize
        write_through
        rotational
        nv_cache
        thin_provisioned
        filename
        removable
        read_only

All done.

# 看一下有 nullio 支援的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_hnd_attr vdisk_nullio -nonkey

Collecting current configuration: done.

        Attribute       Value                                          Writable      KEY
        --------------------------------------------------------------------------------
        type_string     Direct-access device (e.g., magnetic disk)     No            No
        trace_level     out_of_mem                                     Yes           No
                        minor                                          Yes           No
                        pid                                            Yes           No
                        line                                           Yes           No
                        function                                       Yes           No
                        special                                        Yes           No
                        mgmt                                           Yes           No
                        mgmt_dbg                                       Yes           No
        type            0                                              No            No

        Possible trace levels:
          (use trace_level="add < level>", none, all or default to set):
                debug, function, line, pid, entryexit,
                buff, mem, sg, out_of_mem, special,
                scsi, mgmt, minor, mgmt_dbg, scsi_serializing,
                retry, recv_bot, send_bot, recv_top, pr,
                send_top, order,

        Device CREATE attributes available
        ----------------------------------
        removable
        blocksize
        read_only
        rotational

# 看一下有 cdrom 支援的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_hnd_attr vcdrom -nonkey

Collecting current configuration: done.

        Attribute       Value                Writable      KEY
        ------------------------------------------------------
        type_string     CD-ROM device        No            No
        trace_level     out_of_mem           Yes           No
                        minor                Yes           No
                        pid                  Yes           No
                        line                 Yes           No
                        function             Yes           No
                        special              Yes           No
                        mgmt                 Yes           No
                        mgmt_dbg             Yes           No
        type            5                    No            No

        Possible trace levels:
          (use trace_level="add < level>", none, all or default to set):
                debug, function, line, pid, entryexit,
                buff, mem, sg, out_of_mem, special,
                scsi, mgmt, minor, mgmt_dbg, scsi_serializing,
                retry, recv_bot, send_bot, recv_top, pr,
                send_top, order,

All done.

# 看一下有 iscsi driver 支援的屬性
pjack@ubuntu3371:~$ sudo scstadmin -list_drv_attr iscsi --nonkey

Collecting current configuration: done.

        Attribute            Value          Writable      KEY
        -----------------------------------------------------
        open_state           open           No            No
        isns_entity_name     < not set="">  Yes           No
        version              3.0.0-pre1     No            No
        trace_level          out_of_mem     Yes           No
                             minor          Yes           No
                             pid            Yes           No
                             line           Yes           No
                             function       Yes           No
                             special        Yes           No
                             mgmt           Yes           No
                             mgmt_dbg       Yes           No
                             conn           Yes           No
        iSNSServer           < not set="">  Yes           No
        enabled              0              Yes           No

        Possible trace levels:
          (use trace_level="add < level>", none, all or default to set):
                debug, function, line, pid, entryexit,
                buff, mem, sg, out_of_mem, special,
                scsi, mgmt, minor, mgmt_dbg, scsi_serializing,
                retry, recv_bot, send_bot, recv_top, pr,
                send_top, d_write, conn, conn_dbg, iov,
                pdu, net_page,

        Dynamic attributes available
        ----------------------------
        OutgoingUser
        IncomingUser



scstadmin script 內容


把原本的 IET 改接到 SCST,另外也有提到一些 performance fine tune 的建議,另外也有 /sys/kernel/scst_tgt/ 的目錄結構


http://linux-iscsi.org/index.php/ALUA
對於 ALUA 的解釋

Install SCST on Ubuntu 11.10 Server


因為安裝 SCST 需要 patch Linux Kernel,所以目前 Ubuntu 本身不支援這個方案,未來比較有可能支援的是 LIO,不過 LIO 還沒成熟,有支援 Multipath 功能的就只能使用 SCST, 所以目前就暫時先用這個方案了,但真的是一個很麻煩的東西。

Installation 的步驟,先參考這篇來 Patch Kernel
http://www.tomlecluse.be/blog/20110902/scst-and-scstadmin-ubuntu-1104

Install necessary packages
sudo apt-get install fakeroot kernel-wedge build-essential makedumpfile kernel-package libncurses5 libncurses5-dev
sudo apt-get build-dep --no-install-recommends linux-image-$(uname -r)

Get the current kernel source
mkdir /usr/src
cd /usr/src
apt-get source linux-image-$(uname -r)
ln -s /usr/src/linux-3.0.0 linux
cd linux-3.0.0

接下來參考這篇 http://iscsi-scst.sourceforge.net/iscsi-scst-howto.txt

Patch Kernel
svn co https://scst.svn.sourceforge.net/svnroot/scst/trunk scst
cd /usr/src/linux-3.0.0
patch -p1 < $HOME/scst/iscsi-scst/kernel/patches/put_page_callback-3.0.patch
patch -p1 < $HOME/scst/scst/kernel/scst_exec_req_fifo-3.0.patch
make clean
build kernel 之前要先產生 config 檔, 操作方式有好幾種可以選擇, 鳥哥裡面有一篇寫的很清楚,
http://linux.vbird.org/linux_basic/0540kernel.php
分別有 menuconfig / oldconfig / xconfig / gconfig / config 幾種方式

Build Kernel
make oldconfig
make && make modules
make modules_install && make install

Build SCST
make scst scst_install iscsi iscsi_install scstadm scstadm_install

Start SCST
modprobe scst
modprobe scst_vdisk
modprobe iscsi-scst
iscsi-scstd




2011年12月11日 星期日

[轉][新聞] TVBS最新民調

作者: saradinel (sara) 看板: Gossiping
標題: Re: [新聞] TVBS最新民調
時間: Sun Dec 11 01:18:28 2011

以下文章很長,怕被人說沒八卦而被刪掉
因此我先補個跟民調有關的八卦先,根據dpp五都其中之一的某市黨部最新內部民調
立委民調,其中有6席是領先的
請自己猜是哪一都XDDD (我有保密的義務,所以請不要來信問我是哪一都)
-----------------------------------------------------
我在重新統計了一下TVBS民調五都的數據和縣市長選舉的民調數據
發現到一個蠻驚人的事實,那就是TVBS民調雖然不能成功訪問到所有綠的支持者
但卻幾乎可以100%完全訪問到藍的支持者
因此我首先的想法是,假設在TVBS民調中會表態投藍的就一定會去投藍
而未表態或拒訪的就不會投藍
換句話說,會去投藍的就一定會在民調中表態
舉個例子來說,如果某個藍營人選在民調中有50%的支持度
而民調拒訪率為20%的話,就相當於會有全部有效選民中的50%*80%=40%會去投藍
假設投票率為70%時,其得票率就為40%/70%=57%
當然實際上民調中說會去投藍的最後不一定會出門投藍,而同時也會有少數不表態或拒訪
的人,最後卻跑去投藍的,但我這邊事先假設兩者最後相抵的結果,幾乎為0
如果說這個想法所得到的結果跟實際得票率沒相差太多的話,就代表這個想法是可行的
因此我寫出初步的修正公式:
KMT的預測得票率 = 民調中KMT人選的支持度*(100%-拒訪率)/(投票率)
其中投票率要自己事前估測或事後用實際上的投票率來做驗證
最後我統計了一下北北中三都共20次民調
其中先排除蘇嘉全剛參選的26%:57%這個極端值的民調
其他北北中三都共19次民調結果的平均誤差只有3.17%
從這個誤差值來看這個想法是可行的,而這只是初步的預測結果而已
此外我發現了另外一個也很重要的現象 (我們開始把蘇嘉全參選的極端值民調考慮進來)
那就是如果說把這20次民調的初步修正結果,定義其偏差量=初步預測值 - 實際得票率
把這20次民調的偏差量對KMT人選的支持度畫圖的話,其圖形非常接近一條直線
http://ppt.cc/xXOQ
其一次趨勢線的公式為:y=1.4203x-0.6393
R平方也有0.9127
這個結果代表說只要我們在原始的修正公式上,減掉 (1.4203x-0.6393)這個量
那麼平均誤差將會從原本的3.17%明顯降低很多
因此最後可得北北中三都的修正公式為:假設X為KMT人選的支持度 (X單位為%)
KMT人選的預測得票率=X*(100%-拒訪率)/投票率 -1.4203X +0.6393
或者寫成
KMT人選的預測得票率=X*(100%-拒訪率)/投票率 -1.4203X +63.93%
最後我把 北北中三都共20次民調(連蘇嘉全剛參選的那個極端值民調都包含進去)
用這個新公式所得的預測得票率跟實際得票率作圖,水平軸為月份
可得以下的圖形 (藍色為KMT人選各次民調的預測得票率,紅色為實際得票率)
台北市:平均誤差為1.42%
http://ppt.cc/o6l6
新北市:平均誤差為1.58%
http://ppt.cc/(uij
台中市:平均誤差為1.22%
http://ppt.cc/dpbk
可以發現就算民調再怎麼變動,三者的誤差其實都很小
尤其是台中,5月份時的民調是蘇26%:胡57%,到10月份時是蘇34%:胡47%
但是這兩者預測的誤差卻只有1.9%和0.58%
就算民調變動很大,但是預測的得票率變動卻不大,誤差還小到非常恐怖的境界
所以證明了這個公式對於北北中三都,且投票率在7成以上的情況是極為適用的
--------------------------------------------------------------------
至於南二都民調如何修正?
則不能用上述方法,因為南二都的藍營支持者表態率比北北中三都低一些
換個方法來計算,
假設在TVBS民調中 KMT的支持度為 X DPP的民調支持度為 Y 未表態為 100-X-Y
由常理來判斷
1. X愈大,則DPP在未表態當中的得票率就愈高
2. KMT贏愈多,即(X-Y)愈大,則DPP在未表態中的得票率就愈高
因此可列出以下的式子:
DPP得票率 = Y + (100-X-Y)*(A*X*(X-Y)+B) + C
其中A,B,C是待求的參數
我們把實際上南二都共11次民調,以及部份09年縣市長選舉民調
帶進去算,去取一次趨近線方程式,可得:
DPP得票率 = Y + (100-X-Y)*(0.0002*X*(X-Y)+0.55) + 1.2%
接著拿這個公式對南二都的11次民調畫圖,總平均誤差約為2.34%
其中綠線為預測得票率,紅線為實際得票率
大台南市:
http://ppt.cc/-,jZ
平均誤差雖然為3.28%,但是這是因為民調變動太大,比大台中還要大
選前半年民調差距太大:賴59% 郭22%;選前的民調才拉進到:賴47% 郭34%
但是如果只看 選前最近的兩次民調的話,誤差分別只有0.18%和3.44%
民調變動這麼大卻還有這樣的誤差水準,算是不錯了
大高雄市:平均誤差只有1.56%
http://ppt.cc/AAu8
這個預測結果也不用說了,三人參選雖然情況較複雜
卻還是能精準預測陳菊的得票率
----------------------------------------------------
至於如何看待TVBS最近幾次總統選舉民調,可以依這個邏輯來思考
也就是在彰化以北,KMT執政的縣市,視作所有藍營支持者可以完全100%被訪問到
(自己可以假設投票率接近8成,拒訪率的話,TVBS每次都有公佈)
然後雲林以南DPP執政的縣市,則用南二都的方法來算
有興趣的版友自己嘗試看看吧
不過算歸算,這只是統計學上的結果而以
PS:三人競選的話,大家就依自己判斷,把宋的票看要多少給馬
多少給蔡,然後最後有多少是宋的鐵盤
我只能說其實根據我所打聽到的消息
最後的選舉結果,其差距可能會比大家想像的大
至於誰勝誰負,我不能說...

2011年12月8日 星期四

[轉] [問卦] 全世界知名度最高的台灣人?

作者: schooner45 (保持清醒) 看板: Gossiping
標題: Re: [問卦] 全世界知名度最高的台灣人?
時間: Wed Dec 7 01:26:46 2011

數據會說話;知識重要性和網路資訊量,面向是不同的... 最有名的"台灣人"是誰呢?
廣義而言,應是 蔣介石 (知識份量)& 曾雅妮 (資訊量);
``````統治台灣最久的人,空前絕後......
狹義(閩客原)而言,則是 陳水扁 (知識份量)&還是 曾雅妮 (資訊量);詳情參見如下:
``````執政8年+救援N年......
===============曾身為台灣人/曾擁有ROC在台國籍者/長眠台灣的人=================
世界最大百科 世界最大搜尋引擎
維基條目語系數 ; Google資訊條目數
蔣介石: 65語系  3,080,000條
----------------------------以上魔王級-------------------------------
李安: 49語系 5,550,000條
馬英九(美國綠卡): 39語系 21,000,000條
陳水扁: 38語系 6,270,000條
李遠哲: 30語系 453,000條
----------------------------以上尊爵級-------------------------------
蔡英文: 29語系 18,800,000條
蔣經國: 28語系 1,400,000條
鄧麗君: 26語系 3,570,000條
周杰倫: 26語系 14,500,000條
李登輝: 24語系 3,750,000條
金城武(日本籍): 24語系 9,080,000條
鄭成功: 24語系 1,080,000條
宋美齡: 22語系 771,000條
顧維鈞: 21語系 117,000條
蔡依林: 21語系 38,600,000條
吳百福(安藤百福): 20語系 3,270,000條
----------------------------以上傳奇級-------------------------------
舒淇: 18語系 28,400,000條
王力宏:(雙重國籍) 16語系 29,400,000條
侯孝賢: 16語系 871,000條
單國璽: 14語系 431,000條
徐若瑄: 13語系 12,500,000條
徐熙媛: 13語系 4,080,000條
林青霞: 12語系 8,140,000條
林依晨: 12語系 11,800,000條
蕭亞軒: 12語系 3,400,000條
孔祥熙: 11語系 536,000條
曾雅妮; 11語系 111,000,000條
張惠妹: 10語系 4,180,000條
----------------------------以上不凡級-------------------------------
古龍(熊耀華): 9語系 2,820,000條
柏楊(郭衣洞): 9語系 349,000條
林志玲: 9語系 44,600,000條
王祖賢(加拿大籍): 8語系 4,230,000條
王貞治(中華民國籍): 8語系 6,830,000條
馬偕: 8語系 2,110,000條
張艾嘉: 8語系 633,000條
王建民: 8語系 10,200,000條
言承旭: 8語系 7,870,000條
----------------------------以上名人級-------------------------------
PS.所列語系不滿8種(相信還是有漏網之魚啦)or教科書、電視等鮮少提及者恕不列錄。
ex.商業名利極大的徐熙娣、江蕙等,外語條目都不足(麻煩政大阿語系的去編一下);
葬於台灣的八田與一僅有4語系;釋證嚴(王錦雲)僅存於5語系,聖名似未國際化@@
======================PS.參考:世界級巨人的百科條目語系數====================
(這些人的搜尋資訊都是數以億萬計,不贅述矣~從介紹語系數足可看出他們的普世份量)
世紀末救世主 耶穌: 193語系 (最接近神的男人!)
佛祖 釋迦摩尼: 111語系
至聖先師 孔子: 185語系 (最接近耶穌的男人!)
哲學代名詞 蘇格拉底: 129語系
最後先知 穆罕默德: 143語系
草原霸者 成吉思汗: 111語系
站在巨人的肩膀 牛頓: 182語系
共和之父 華盛頓: 126語系
字典沒有失敗 拿破崙: 135語系
歐洲的祖母 維多利亞: 86語系
共產主義之父 馬克思: 139語系
蘇維埃國家之父 列寧: 130語系
全壘打王 貝比魯斯: 31語系 (ps.比王貞治多很多......)
明治天皇 睦仁: 45語系
鐵拳無敵 孫文: 82語系
魔頭 希特勒: 155語系
奸雄 史達林: 126語系
共匪 毛澤東: 110語系
喜劇之王 卓別林: 131語系 (ps.周星馳25語系)
科學家象徵 愛因斯坦: 152語系
貓王 艾維斯普里斯萊: 107語系
性感象徵 瑪麗蓮夢露: 118語系 (ps.居里夫人112語系、聖女貞德100語系)
功夫代名詞 李小龍: 80語系 (ps.普世知名廣度最大的"中國人明星")
國際級鼻子 成龍: 70語系 (ps.周潤發42語系、劉德華23語系)
流行之王 麥可傑克遜: 144語系
籃球之神 麥可喬丹: 68語系
足球金童 貝克漢: 73語系
韓流代表 少女時代: 33語系 (ps.僅次於台灣的蔣介石、李安、馬扁)
中二代表 小賈斯汀: 78語系

2011年12月5日 星期一

[轉] 2011年終漫畫銷售排行榜


 作者  joug (好東西不簽嗎)                                    站內  Gossiping

 標題  [新聞] 2011年終漫畫銷售排行榜


= 2011年漫畫年度銷售前10名 =

▼第10名:《Gantz殺戮都市》銷售量406萬本
http://images.gamme.com.tw/news/2011/12/1/o5yWoaOYl56VqQ.jpg

第9名:《只想告訴你》銷售量411萬本
http://images.gamme.com.tw/news/2011/12/1/o5yWoaOcl56Vqg.jpg

第8名:《BLEACH死神》銷售量419萬本
http://images.gamme.com.tw/news/2011/12/1/o5yWoaSVl56Vqw.jpg

第7名:《爆漫王。》銷售量440萬本
http://images.gamme.com.tw/news/2011/12/1/o5yWoaSZl56VrA.jpg

第6名:《銀魂》銷售量442萬本
http://images.gamme.com.tw/news/2011/12/1/o5yWoaSdl56VrQ.jpg

第5名:《美食獵人》銷售量467萬本
http://images.gamme.com.tw/news/2011/12/1/o5yWoaWXl56Vrg.jpg

第4名:《魔導少年》銷售量470萬本,成為唯一殺入排行榜的非集英社漫畫
http://images.gamme.com.tw/news/2011/12/1/o5yWoaWal56Vrw.jpg

第3名:《青之驅魔師》銷售量522萬本

第2名:《火影忍者》銷售量687萬本

堂堂第1名當然是~今年一直在破記錄的《海賊王》囉!恭喜恭喜!!

▼海賊王還是一如往常的瘋狂,3800萬本銷壽量,從第2名起的銷售量一直累加到

第9名才超過3800萬,這真是太恐怖了~*
在另一個層面來說也是天才的人也上榜了

▼被宅宅和讀者們婊了一整年的富奸老師,除了「天才」以外沒有別的形容

詞更適合他了。2010.11兩年只出了兩本《獵人》(還都是在今年的後半出的)

竟然還名列第13名,當漫畫家能當到這個程度也算是此生無枉己了


2011漫畫銷售排行榜1-25名


iSCSI written by Greg Ferro 筆記

http://etherealmind.com/iscsi-network-designs-part-1-some-basics/

iSCSI initiator performance

When implementing iSCSI in your server operating system you have two choices, software or hardware (using Host Block Adapter).
  • Software: The TCP/IP packet is generated by the operating system using your core CPU
  • Hardware: Host Bus Adapter is a PCI card that performs the TCP processing. This is known as TCP Offload and the cards are generally known as TCP Offload Engines or TOE.

http://etherealmind.com/iscsi-network-designs-part-2-simple-scaling/

Increase the bandwidth

Use Link Aggregation Control Protocol (LACP) or Etherchannel to increase the bandwidth to between 2-6 gigabits per second

The are some pre-conditions:
1) server NICs and drivers must support LACP
2) switches must support LACP
3) switches must support enough LACP bundles. (cheaper switches may only support a few LACP bundles per switch).
4) all bundles must terminate on the same switch (or switch stack or chassis).



Software Initiators

  • using a general purpose CPU to perform the data transformation
  • it is not optimised for performance

TCP Offload Engines (TOE)

  • TOE cards are able to improve the TCP performance of a server

Host Bus Adapters

  • generic term for connecting the I/O bus of your server to an external system
  • iSCSI Header and Data Digest calculations are very CPU intensive. Only a full iSCSI offload HBA has the logic built into the ASIC to accelerate these calculations.
http://etherealmind.com/iscsi-part-4-fibrechannel-iscsi-integration/

None 


Redundancy


iSCSI implements its HA features. There are three ways to achieve this:
  1. Link Aggregation – LACP
  2. iSCSI Multipathing – Active / Standby
  3. iSCSI Multipathing – Active / Active

Link Aggregation – Etherchannel / LACP

  • two network cards in the servers
  • the two network cards must connect to the same Cisco switch (2)
  • network adapters and drivers must have support for LACP
  • at least one switch with supports LACP (sometimes know as Etherchannel)
  • you must be able to configure both the server drivers and switch configuration
    其實這不太算是 Redundany,因為 NIC 在同一台機器上,通常會壞的不是網卡,而是其它東西,機器本身如果出了問題,LACP 也幫不上忙,LACP 的好處是可以增加讀寫的 Performance,尤其是寫入的部份,作為 LB 倒是滿適合的。另外是也需要 Switch 有支援才能做到這個功能。

iSCSI Multipathing Active / Standby => MC/S (Multiple Connections per Session)

This is defined in the iSCSI RFC as the method for achieving high availability. The iSCSI initiator will initiate at least two TCP connections to the iSCSI target. Data will flow down the primary connection until a failure is detected and data will then be diverted to the second connection.


我覺得作者這部份的描述是錯誤的,找了很多資料,我認為圖的部份以及文字的部份是在描述 MC/S 這個方式,用 Active/Standby 來當標題並不合適

iSCSI Multipathing Active / Active => MPIO (Multi-Path Input/Output)

MPIO 本身有兩種方案,分別就是 Active/Standby 及 Active/Active,所以我覺得作者的標題下的不太正確,相關文章我覺得這篇寫的最清楚。

http://blog.xuite.net/weirchen/blog/22184665

現在支援較豐富的是 MPIO,我個人認為是因為 MC/S的限制較多,除了不能針對每一個 Lun 來做設定,他似乎也間接限定了 Target 的兩個連線必須連到同一台主機的兩個 NIC,不過這有待確認,但肯定的是如果主機背後是 Distributed Storage Server,那使用 MPIO 可以將連線連到不同的主機,只要他們能連接到同一塊 Volume。

Conclusion


2011年12月1日 星期四

Open Source License

為了要搞懂那些 License 是 commercial friendly,所以收集了一些比較的連結。台灣的老闆對於開放 source code 還是都會感到害怕,其實這也無可厚非,雖然這些 License 還是保障著作權,但是卻可能讓敵方很方便的抄襲你的設計,先不談軟體要怎麼判定有沒有侵犯著作權,光是打官司要耗費的人力財力,就會先讓人退縮一步了吧! 再來是公開源代碼也容易把自己的缺點或是漏洞曝露在敵人眼中,我覺得這也是讓人很頭痛的問題。

現在有的 opensource license

中文:
  • 對於商業軟體來說,是可以引用LGPL的函式庫的,著名的LGPL自由軟體有Mozilla跟OpenOffice.Org
  • BSD:開發者有權選擇是否要開放原始碼,或是做為商業用途
http://gemmy886.blogspot.com/2008/01/bsdapachegpllgplmit.html
  • BSD 代碼鼓勵代碼共享,但需要尊重代碼作者的著作權。BSD由於允許使用者修改和重新發佈代碼,也允許使用或在BSD代碼上開發商業軟件發佈和銷售,因此是對 商業集成很友好的協議
  • Apache Licence是著名的非盈利開源組織Apache採用的協議。該協議和BSD類似,同樣鼓勵代碼共享和尊重原作者的著作權,同樣允許代碼修改,再發佈
  • MIT是和BSD一樣寬范的許可協議,作者只想保留版權,而無任何其他了限制
英文:

總結:最好的商業選擇是 MIT or BSD or Apache,次之是 LGPL,GPL則是避免,感染力十分的強,處理的不好會連帶整個產品都被感染



2011年11月20日 星期日

Python 2.7 Standard Library 筆記 -- Regular Expression

教學連結
http://docs.python.org/howto/regex.html#regex-howto

re Module
http://docs.python.org/library/re.html


  • \d 就是 [0-9] \D 則是 [^0-9]
  • \s 就是 [ \t\n\r\f\v] \S 則是 [^ \t\n\r\f\v]
  • \w 就是 [a-zA-Z0-9_] \S 則是 [^a-zA-Z0-9_]
  • [] 是一堆字元的集合, 只要出現裡面任一字元, 就算符合
  • * 是重覆  0 ~ 無限多次
  • + 是重覆 1 ~ 無限多次
  • ? 是重覆 0 或 1 次

  • re.compile 會回傳一個 pattern object,利用這個 pattern object 可以持續的分解一段文字,還滿好用的
  • class SRE_Pattern(__builtin__.object)
     |  Compiled regular expression objects
     |
     |  Methods defined here:
     |
     |  findall(...)
     |      findall(string[, pos[, endpos]]) --> list.
     |      Return a list of all non-overlapping matches of pattern in string.
     |
     |  finditer(...)
     |      finditer(string[, pos[, endpos]]) --> iterator.
     |      Return an iterator over all non-overlapping matches for the
     |      RE pattern in string. For each match, the iterator returns a
     |      match object.
     |
     |  match(...)
     |      match(string[, pos[, endpos]]) --> match object or None.
     |      Matches zero or more characters at the beginning of the string
     |
     |  scanner(...)
     |
     |  search(...)
     |      search(string[, pos[, endpos]]) --> match object or None.
     |      Scan through string looking for a match, and return a corresponding
     |      MatchObject instance. Return None if no position in the string matches.
     |
     |  split(...)
     |      split(string[, maxsplit = 0])  --> list.
     |      Split string by the occurrences of pattern.
     |
     |  sub(...)
     |      sub(repl, string[, count = 0]) --> newstring
     |      Return the string obtained by replacing the leftmost non-overlapping
     |      occurrences of pattern in string by the replacement repl.
     |
     |  subn(...)
     |      subn(repl, string[, count = 0]) --> (newstring, number of subs)
     |      Return the tuple (new_string, number_of_subs_made) found by replacing
     |      the leftmost non-overlapping occurrences of pattern with the
     |      replacement repl.
     |
    
    
  • 要注意 raw string 及非 raw string 的差別,一般會直接使用 raw string,比較直覺
  • # 第一個方案用一般  string 來找尋 '\n' 必須要輸入 "\\n"
    >>> p  = re.compile('\\n', re.IGNORECASE)   
    >>> p.findall("\np")
    ['\n']
    >>> p.findall("\\np")
    []
    # 第二個方案用 raw string, 就直接輸入 "\n" 就可以了,效果是一樣的
    >>> p  = re.compile(r'\n', re.IGNORECASE)
    >>> p.findall("\np")
    ['\n']
    >>> p.findall("\\np")
    []
    >>> print p.findall("\np")[0]
    
  • Compilation Flags
    • IGNORECASE, 這個應該很方便, 可以省去很多必須注意的小地方
    • MULTILINE, 可以自動把每一行分開解析
  • A | B 可以找尋 A 或 B, A 和 B 分別是一個 RE
  • ^A 可以指定字串起始點必須要符合 A, A 是一個 RE
    • 不過在集合 [] 內, ^ 是當反相的意思
  • A$ 可以指定字串尾巴必須要符合 A, A 是一個 RE
  • \bS\b 用來指明要找尋的字串S前面或是後面必須要有分隔的字元
  • \BS\B 剛好是\b 的相反, 字串 S 的前面或是後面不可以是分隔的字元
  • () 用在區隔 group, 可以讓你一次在一個字串內找尋兩個 pattern, 甚至這兩個 pattern 是有交互作用的
  • >>> p = re.compile('(a(b)c)d')
    >>> m = p.match('abcd')
    >>> m.group(0)
    'abcd'
    >>> m.group(1)
    'abc'
    >>> m.group(2)
    'b'
    
    • (?P...) ,指定 group 的名字, (?P=name) 是舊的寫法
    • (?:...), 不指定 group 的名字, 只 mapping 但不抓回來, 這邊的寫法有點難以理解
    • >>> m = re.match("([abc])+", "abc")
      >>> m.groups()
      ('c',)
      >>> m = re.match("(?:[abc])+", "abc")
      >>> m.groups()
      ()
      
    • (...)\1 可以用來指明第幾個 group, \1 表示要搜尋第一個 group
  • Splitting Strings
    • 也可以利用 RE 來 split string, 符合的字串將會被消去, 然後分段整個字串
    • 如果不想把符合的字串消去, 就必須加上 group
    • >>> p = re.compile(r'\W+')
      >>> p2 = re.compile(r'(\W+)')
      >>> p.split('This... is a test.')
      ['This', 'is', 'a', 'test', '']
      >>> p2.split('This... is a test.')
      ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']
      
  • Search and Replace
    • 符合的 pattern 可以用在 Replace Rule 當中, 這三種表示法都是同樣的意思 \1 = \g<1> = \g
  • *?、+?、?? 都是 Non-Greedy


2011年11月15日 星期二

LVM 中製作 snapshot


兩個範例

Example 1: 普通用法
lvcreate -i 3 -I 8 -L 100 vg00
Tries to create a striped logical volume with 3 stripes, a stripesize of 8KB and a size of 100MB in the volume group named vg00. The logical volume name will be chosen by lvcreate.


Example 2: 從一個已存在的 image 製作 snapshot
lvcreate --size 100m --snapshot --name snap /dev/vg00/lvol1

creates a snapshot logical volume named /dev/vg00/snap which has access to the contents of the original logical volume named /dev/vg00/lvol1 at snapshot logical volume creation time. If the original logical volume contains a file system, you can mount the snapshot logical volume on an arbitrary directory in order to access the contents of the filesystem to run a backup while the original filesystem is updated.

2011年11月10日 星期四

iSCSI Target Management

收集一下目前可以管理 iSCSI Target 的東西,目前有使用過的

各種 Solution
比較
IET 的說明
  • A iSCSI target driver for Ethernet adapters, which tgt has used as a base for istgt

Tgt 的說明

  • Designed to work with multiple SCSI type devices and integrate them into the Linux kernel in a standard way
  • implementing a significant portion of tgt in user space while maintaining performance comparable to a target driver implemented in kernel space
  • The first author has maintained IET. The failure to push it into the mainline kernel is one of the reasons why tgt was born.

SCST 的說明
  • all the SCST components reside in kernel space



  1. 在使用上 IET 需要先設置 conf 檔案,雖然也可以用指令動態管理,但卻沒有方法更新 Conf 檔
  2. Tgt 則是全部用指令,之後再 output 設置到 conf 檔案
  3. Performance 似乎在 Kernal space 執行的  SCST 最好
  4. 根據這篇,似乎 Ubuntu 不支援 SCST,有點可惜
  5. LIO 還在開發中,但提供的介面很齊全,不管是 CLI or LIB 都有,在系統整合時應該會方便不少,但可惜它的穩定性以及開發時間都還無法滿足我的要求。


2011年11月8日 星期二

sudo with redirect syntax


執行這段時發現無法執行,看了半天才發現他可能是先執行 (sudo echo hello) 然後再導向檔案,所以就已經沒有 root 的身份

pjack@ubuntu1104-64-5:/etc/ceph/a$ sudo echo hello > tmp.txt
bash: tmp.txt: Permission denied


網路上有找到兩個解法


# 第一種
sudo sh -c "echo hello >> tmp.txt"

# 第二種
echo "hello" | sudo tee tmp.txt

2011年11月1日 星期二

Python 學習手冊第三版筆記 (七)


CH.27 例外事件基礎

with/as 環境管理器的敘述滿難懂的,感覺大部份的 with/as 都可以用 try/finally 實作完成,但好處似乎是物件可以事先把對 exception 的處理定義好,ex: 檔案碰到 exception 時會自動關閉,等到別人使用你的物件時,只要透過 with/as 就可以正確的處理 exception ,而不需要讓每個人都煩惱 "如果遇到 exception ,我是否需要去關檔?"

CH.28 例外事件物件

類別式例外事件的概念在 Java 中已發展的很完全,這讓我覺得原作者果然很懶惰 :P 所以只想用最簡單的方式來處理 Exception,不過看的出來 Python 在這部份的設計很明顯的不敷使用,也間接造成了光是 raise 就有很多種奇怪怪的寫法,書的作者也只能嘆氣囉! 這就是 Design 或是架構在一開始沒有設計好的後遺症

CH.29 例外事件的設計


>>> help(sys.exc_info)
Help on built-in function exc_info in module sys:

exc_info(...)
    exc_info() -> (type, value, traceback)
    
    Return information about the most recent exception caught by an except
    clause in the current stack frame or in an older stack frame.



>>> help(os.popen)
Help on built-in function popen in module nt:

popen(...)
    popen(command [, mode='r' [, bufsize]]) -> pipe
    
    Open a pipe to/from a command returning a file object.

>>> help(os.system)
Help on built-in function system in module nt:

system(...)
    system(command) -> exit_status
    
    Execute the command (a string) in a subshell.


PyDoc 、 PyChecker、PyUnit 好用的三大工具!


看到這裡我終於把這本書都讀完囉!

2011年10月31日 星期一

Python 學習手冊第三版筆記 (六)

CH.22 OOP: 大藍圖

  • 可多重繼承,我不一向不太喜歡這個,比較喜歡 Java 的單一繼承,事情有時會簡單一點
  • 每個函式必須加上 self ,我也覺得這個很多餘

CH.23 類別撰碼基礎

  • 和 def 一樣是可執行敘述,執行完後就打包成一個 class 物件,而且是可以動態增加元素
  • >>> class rec: pass    # 一開始裡面什麼都沒有
    
    >>> rec.name = 'Bob'      # 動態增加了一個欄位
    >>> x = rec()
    >>> x.name                      #  x 是 rec 的物件,可以存取到 name
    'Bob'
    >>> x.age                         # 想要存取 age 這個欄位會失敗,因為不存在
    
    Traceback (most recent call last):
      File "< pyshell#20>", line 1, in < module>
        x.age
    AttributeError: rec instance has no attribute 'age'
    >>> rec.age = 3              # 那我們就幫他增加 age 這個欄位吧!
    >>> x.age                        #  可以成功增加
    3
    
    除此之外,我們甚至可以動態增加物件裡面的欄位,不過這就不會影響到原生 Class
    >>> class rec:
     name = 'BoB'
     age = 3
    
    >>> x = rec()
    >>> x.length = 180
    >>> x.length                # 成功增加了 length 這個欄位
    180
    >>> rec.length            # 原生的 rec 仍然沒有這個欄位
    
    Traceback (most recent call last):
      File "< pyshell#34>", line 1, in < module>
        rec.length
    AttributeError: class rec has no attribute 'length'
  • __init__ 是建構子,__del__是解構子,在學C++時有聽過三一律,不知道 Python 有沒有符合這樣的特性
  • 可以利用 __add__、__mul__ 覆蓋運算子

另外函式也是可以輕易的被動態換掉,只要第一個參數是 Self 即可,我想這樣稍微解釋了為什麼他規定要每個函式第一個參數都是 Self,這樣的寫法其實很像我們用 C 在模擬 OOP 時,利用第一個參數來傳送 Instance 的道理是一樣的,所以要說 Python 是很先進的 OOP 的語法,好像又不是那麼一回事,只能說他反璞歸真吧~~

>>> def upperName(self):
 return self.name.upper()

>>> rec.method = upperName
>>> x.method()
'BOB'

CH.24 類別撰碼細節

我突然領悟到為什麼書一開頭有講到 Python 的 Class 類別長的像其它 OOP 語言但其實內裡完全不是那麼一回事。一般 OOP 的 Class 是一種宣告,存在於 ROM 之中,而且在一般狀況下會事先 loading 到 Memory 當中,然後 Instance 是 Class 的實作,每份 Instance 都是獨立的個體、獨立的 Memory,換一種方式來說 Class 的宣告是死的,Instance 是活的。然而 Python 的設計我覺得是一個很偷懶的設計,Class 本身就是一個活著的物件,而每個 Instance 看似是獨立的個體,但其實是障眼法,它其實只做了個身體,然後等你要用到右手的時候,它才做個右手給你,等你要用到左手的時候,它才做個左手給你,不然平常它都是直接偷用 Class 內的東西,所以如果你改了 Class 內的值,也會間接影響到這些 Instance,我看到書裡面這個範例時,快笑翻了,怎麼會有這麼偷懶的語言。

>>> class SharedData:
 spam = 42

>>> x = SharedData()
>>> y = SharedData()
>>> x.spam, y.spam
(42, 42)
>>> SharedData.spam = 99
>>> x.spam, y.spam, SharedData.spam
(99, 99, 99)
>>> x.spam = 88
>>> x.spam, y.spam, SharedData.spam
(88, 99, 99)

而且 Class 的宣告和 Instance 的生成,兩者之間看似很有關係,但這關係很容易被破壞,你除了可以在 Instance 上面加上原來就該有的手、腳外,你高興的話也可以臨時在 Class 上增加個翅膀,也可以臨時在 Instance 上增加個尾巴,然後也可以任意的把眼睛的功能變成透視眼功能,在這樣惡搞之下,Instance 其實可能會長的和 Class 一點也不像,不過幸好的是只能做"加法",而不能做"減法",所以 Instance 至少會保有 Class 所有的欄位及功能。

繼承的部份和 Instance 也很像,關係看似很緊,但其實也是很薄弱,Super class 可以動態亂改,Inheritor 也可以動態亂改,看了半天,我覺得繼承其實也是一種 Instance,只是他是一個有名字、可以方便再利用的 Instance。

Java 中有 Interface,C++ 中有 virtual function,Python 裡面沒有這樣的概念,但在實作上卻可以做的出來,只是如果忘了實作的話要等到要用到時才會發現。(這就是所謂了要吃飯時才發現飯忘了煮嗎?!天呀!真的是偷懶到極點的語言)

>>> class Super:
 def delegate(self):
  self.action()

  
>>> class Provider(Super):
 def action(self):
  print 'in Provider'

  
>>> x = Super()
>>> x.delegate()

Traceback (most recent call last):
  File "< pyshell#75>", line 1, in < module>
    x.delegate()
  File "< pyshell#69>", line 3, in delegate
    self.action()
AttributeError: Super instance has no attribute 'action'
>>> x = Provider()
>>> x.delegate()
in Provider


看到這裡其實也突然讓我發現一個事實,Python 的 method binding 在 def / class 中是不會即時檢查的,也不會事先 linking,而是動態的 linking,所以即使用了一個沒有宣告的函式或是物件,也必須要等到真的有被用到時,才會發現這個事情,但也因為這樣的設計,當你要寫兩個會互相用到的函式(放在不同的模組內),而必須互相 import 時卻不會出事

import modb

def funcA(x):
    if x == 1:
        return 0
    return 1 + modb.funcB(x /2)

class ClassA:
    def getInterClass():
        x = modb.ClassB()
        return x


import moda

def funcB(x):
    if x == 1:
        return 1
    return 1 + moda.funcA(x + 1)

class ClassB:
    def getInnerClass():
        x = moda.ClassA()
        return x



接下來看到 __getitem__ 的應用,書中寫到"買一送一堆",真的是太傳神了,而且我覺得這真的很強大,和__iter__不同的是,反覆器只能繞行一次,而索引運算式則可以一直重覆使用,不過反覆器的用法在寫程式上比較直覺。要解決這樣的問題可以做一個反覆器生成器出來。

__getattr__ 和 __setattr__ 就先跳過不看,太複雜了,竟然是用在實作 private 特性。



CH.25 類別的設計

getattr(X,N) 和 X.__dict__[N] 差異在於,前者也會執行繼承搜尋,但後者不會!

有幾個內建的屬性我覺得還滿重要的,雖然少用但在重要時刻可能會派上用場,特別是 Debug 時

  • 每個類別都有內建 __name__來顯示類別的名字
  • 每個類別都有內建 __bases__ 來顯示其繼承的類別
  • >>> class A: pass
    >>> class B: pass
    >>> class C(A,B): pass
    >>> C.__name__
    'C'
    >>> C.__bases__
    (< class __main__.A at 0x000000000279EF48>, < class __main__.B at 0x000000000279EFA8>)
    >>> C.__bases__[0].__name__
    'A'
    
    
  • __class__ ,每一個實體都可以藉此來辨別他的類別
  • >>> class sample:
     pass
    
    >>> x = sample()
    >>> x.__class__
    < class __main__.sample at 0x000000000279EEE8>
    
  • 每個類別及實體都有 __dict__ 來表示其擁有的屬性,但不包含繼承來的
  • 可以使用 dir 函式來找出所有的屬性,包括自動繼承的部份
  • >>> class C(A,B): pass
    >>> C.__dict__
    {'__module__': '__main__', '__doc__': None}
    >>> dir(C)
    ['__doc__', '__module__']
    >>> x = C()
    >>> x.__dict__
    {}
    >>> dir(x)
    ['__doc__', '__module__']
    
無綁束類別方法物件:必須要明確提供實體物件作為第一個引數 綁束實體方法物件: self + 函式配對,不必再另外傳入 self 兩種除了在使用方法上不一樣外,其它內建的屬性幾乎都一樣,只有 im_self 不同

>>> class Spam():
 def doit(): pass
>>> Spam.doit
< unbound method Spam.doit>
>>> x = Spam()
>>> x.doit
< bound method Spam.doit of <__main__.Spam instance at 0x00000000027A3CC8>>
>>> x.doit.__dict__
{}
>>> Spam.doit.__dict__
{}
>>> dir(x.doit)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'im_class', 'im_func', 'im_self']
>>> dir(Spam.doit)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'im_class', 'im_func', 'im_self']

>>> x.doit.im_self
<__main__.Spam instance at 0x00000000027A3188>
>>> Spam.doit.im_self

__doc__ 可以取得註解,註解必須寫下類別或是函式宣告的下一行



CH.26 高等類別議題
類別內以 "__" 開頭的屬性會被重新命名成 _[Classname]__[原始名稱],不論是一般變數或是函式,但在類別內的宣告時仍然可以用原始名稱來存取,但我覺得 Python 的作者發明這樣的東西其實也不是真的私有化,如果真的要解決書中的問題,可以發明關鍵字 "private" ,不是更乾脆?! 再來是靜態方法及類別方法之間的轉換可以靠 staticmethod 及 classmethod 我覺得也滿醜的,為什麼不用 static 這樣的關鍵字來處理? 更何況打從一開始,我就覺得 Python 是給懶人用的,根本不需要私有化及靜態方法,硬加上這些功能有點四不像。
__slots__ 可能會造成實體沒有 __dict__,以下是一個例子,不但影響了實體,其實連類別的 __dict__ 也產生了變化
>>> class limiter(object):
 __slots__  = ['age', 'name']
>>> x = limiter()
>>> limiter.__dict__
< dictproxy object at 0x00000000027A9108>
>>> x.__dict__

Traceback (most recent call last):
  File "< pyshell#169>", line 1, in < module>
    x.__dict__
AttributeError: 'limiter' object has no attribute '__dict__'
>>> dir(limiter)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'age', 'name']
>>> dir(x)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'age', 'name']
靜態方法、類別方法、一般方法的定義都不太一樣,尤其是"類別方法" ,被宣告成靜態方法後,不管是透過類別或是透過實體去呼叫,都只是一般的函式而己,不需要管是否有綁定,再來是實體內的函式都是有被綁定,透過類別的函式,如果有宣告 classmethod ,那就變成綁定的函式,但不管呼叫的是類別或是實體,都是綁定 class。
class Multi:
    def imeth(self, x):
        print self, x
    def smeth(x):
        print x
    def cmeth(cls, x):
        print cls, x
    smeth = staticmethod(smeth)
    cmeth = classmethod(cmeth)

>>> Multi.imeth
< unbound method Multi.imeth>                         # 非綁定
>>> Multi.smeth
< function smeth at 0x0000000002773E48>     # 一般函式
>>> Multi.cmeth
< bound method classobj.cmeth of < class __main__.Multi at 0x000000000276E6A8>>   # 綁定 class

>>> y = Multi()
>>> y.imeth
< bound method Multi.imeth of <__main__.Multi instance at 0x0000000002774D88>>   # 綁定 instance
>>> y.smeth
< function smeth at 0x0000000002773E48>   
>>> y.cmeth
< bound method classobj.cmeth of < class __main__.Multi at 0x000000000276E6A8>>   # 綁定 class

>>> Multi.imeth.im_self
>>> Multi.smeth.im_self

Traceback (most recent call last):
  File "< pyshell#297>", line 1, in < module>
    Multi.smeth.im_self
AttributeError: 'function' object has no attribute 'im_self'
>>> Multi.cmeth.im_self
< class __main__.Multi at 0x000000000270E6A8>


>>> y.imeth.im_self
<__main__.Multi instance at 0x0000000002713D08>
>>> y.smeth.im_self

Traceback (most recent call last):
  File "< pyshell#293>", line 1, in < module>
    y.smeth.im_self
AttributeError: 'function' object has no attribute 'im_self'
>>> y.cmeth.im_self
< class __main__.Multi at 0x000000000270E6A8>