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

2012-09-02 23:40:07 +08:00
 Hualin
大家好,最近在寫一個小程序,思路是這樣的:

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

方案一
== 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。
2540 次点击
所在节点    Python
5 条回复
Hualin
2012-09-02 23:51:01 +08:00
直接問了,Comprehensive list 表達式的效率怎麼樣?跟直接寫循環比?估計是一樣的吧。
ewangke
2012-09-03 01:36:09 +08:00
@Hualin 建议google一下generator

http://lmgtfy.com/?q=python+generator
ewangke
2012-09-03 01:37:26 +08:00
Hualin
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
2012-09-03 03:05:04 +08:00
@Hualin generator用的是yield,理论上绝不会比list comprehension慢,尤其在处理I/O的时候。

建议先写最直观的代码实现逻辑,再profile一下,看看空间有没有性能问题,问题在哪里。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/46750

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX