V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Hualin
V2EX  ›  Python

『疑問』python's Unhashable type and comprehensive list

  •  
  •   Hualin · 2012-09-02 23:40:07 +08:00 · 2649 次点击
    这是一个创建于 4497 天前的主题,其中的信息可能已经有所发展或是发生改变。
    大家好,最近在寫一個小程序,思路是這樣的:

    有一堆數據點,每個數據點包括其坐標和好幾個屬性字段,一下代碼有兩種實現方式,請原諒我不會在這裡站代碼貼圖:

    方案一
    == python 偽 code ==
    ins = 1000 # 數據實例的個數
    dim = 100 # 數據坐標的維數

    import numpy as np

    class attributes: # 數據點的屬性容器
    def __init__(self, ins):
    self.TRE = np.empty(shape(ins, 1), dtype = str) # 真實數據標記序列
    self.PRD = np.empty(shape(ins, 1), dtype = str) # 估計數據標記序列
    self.ERR = np.empty(shape(ins, 1), dtype = bool) # 估計錯誤標記序列
    self.DSC = np.empty(shape(ins, 1), dtype = float) # 估計值序列

    class space: # 數據空間容器
    def __ init__(self, ins, dim):
    self.mtx = np.array(shape = (ins, dim), dtype = float) # 數據坐標矩陣
    self.atb = attributes(ins) # 數據屬性容器

    == python 偽 code ==
    評價:屬性字段是類的成員變量,不好查詢,如果要擴展,必須繼承該類,而往後的代碼如果要用該字段也要寫繼承原有的類,然後寫針對該字段操作的代碼。


    方案二

    == python 偽 code ==

    class dot: # 單個數據點
    def __init__(self):
    # 在此定義你的數據格式
    self.cdt = (0,0) # 二維數據坐標
    self.atb = {TRE: false, 'PRD': False, 'ERR': False} # 數據屬性

    class space: # 數據空間容器
    def __init__(self, ins):
    self.dataset = [dot() for each in range(ins)]

    == python 偽 code ==
    評價:對單個數據點定義,而不是對一個數據序列進行定義。字典類的成員變量方便了今後代碼的查詢和擴展,也不用從新寫方法,可以將查詢字段作為參數。

    但代碼效率不高,因為:
    方案一是定義一個數據序列,用的是 numpy 的 ndarray。後來的操作基本也是針對一個數據集,即對於一個數據序列的子集,為了方便應用 numpy 固有的數據操作 feature。

    方案二更多的是用 python 自身的數據結構,而非 numpy。但兩種實現不可兼得,因為 字典類數據結構無法添加一個序列子項,因為 ndarray 是 unhashable type,故只能方案二也就只能定義單個數據點。

    後來我注意到可以用 comprehensive list 表達式。例如,如果我後來對數據集操作,其實無須用一個循環把要操作的點遍歷一邊,還是可以用 numpy 的 feature,但要臨時建一個 numpy.ndarray 的實例:
    arr = np.ndarray([each.cdt for each in self.dateset])

    這樣代碼是美觀了,但我不知道這樣的實現效率如何,有沒有方案一那樣直接定義一個數據序列然後直接對其進行操作快?

    所以請教大家這兩種方案我該選哪種,還是另有實現方式?

    寫的有點多,最近一點 python 的疑惑。Thank you for reading。
    5 条回复    1970-01-01 08:00:00 +08:00
    Hualin
        1
    Hualin  
    OP
       2012-09-02 23:51:01 +08:00
    直接問了,Comprehensive list 表達式的效率怎麼樣?跟直接寫循環比?估計是一樣的吧。
    ewangke
        2
    ewangke  
       2012-09-03 01:36:09 +08:00
    @Hualin 建议google一下generator

    http://lmgtfy.com/?q=python+generator
    ewangke
        3
    ewangke  
       2012-09-03 01:37:26 +08:00
    Hualin
        4
    Hualin  
    OP
       2012-09-03 02:00:53 +08:00
    @ewangke comprehensive list 感覺夠用了。
    比如:
    arr = np.ndarray([d.cdt for d in lstdot if d.atb['keyword'] == 'example'])
    ewangke
        5
    ewangke  
       2012-09-03 03:05:04 +08:00
    @Hualin generator用的是yield,理论上绝不会比list comprehension慢,尤其在处理I/O的时候。

    建议先写最直观的代码实现逻辑,再profile一下,看看空间有没有性能问题,问题在哪里。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1199 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 18:10 · PVG 02:10 · LAX 10:10 · JFK 13:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.