python定义词典_python – 自定义类是一个字典,但初始化没有字典副本?
出于易讀性的目的,我希望有一個自定義類,其行為與dict完全相同(但是帶有有意義的類型,而不是更通用的dict類型):
class Derivatives(dict):
"Dictionary that represents the derivatives."
現在,有沒有一種方法可以以不涉及副本的方式構建此類的新對象?天真的用法
derivs = Derivatives({var: 1}) # var is a Python object
實際上創建了作為參數傳遞的字典的副本,出于效率原因,我希望避免使用該副本.
我試圖繞過副本但是在CPython中無法更改dict的類:
class Derivatives(dict):
def __new__(cls, init_dict):
init_dict.__class__ = cls # Fails with __class__ assignment: only for heap types
return init_dict
我希望能夠為程序操作的字典提供顯式類名,并且能夠有效地構建這樣的字典(而不是強制復制Python字典).這在Python中有效嗎?
PS:用例可能是單鍵Derivatives的100,000個創建,其中鍵是變量(不是字符串,所以沒有關鍵字初始化).這實際上并不慢,所以“效率原因”在這里意味著更像“優雅”:理想情況下,當不需要副本時,不需要浪費時間復制.因此,在這個特殊情況下,問題更多的是Python在這里帶來的優雅/清晰度,而不是運行速度.
最佳答案 TL; DR:除非你用C做,否則沒有通用的方法.
答案很長:
dict類是用C實現的.因此,沒有辦法訪問它的內部屬性 – 最重要的是,它是內部哈希表,除非你使用C.
在C中,您只需將表示哈希表的指針復制到對象中,而無需迭代dict(鍵,值)對并將它們插入到對象中. (當然,它比這更復雜.請注意,我省略了內存管理細節).
更長的回答:
我不確定你為什么關心效率.
Python將參數作為引用傳遞.除非您明確告知,否則很少每個副本都有.
我在評論中讀到你不能使用命名參數,因為鍵是實際的Python對象.這讓我明白你擔心復制dict鍵(也許是值).但是,即使是字典鍵也不會被復制,并通過引用傳遞!考慮以下代碼:
class Test:
def __init__(self, x, y):
self.x = x
self.y = y
def __hash__(self):
return self.x
t = Test(1, 2)
print(t.y) # prints 2
d = {t: 1}
print(d[t]) # prints 1
keys = list(d.keys())
keys[0].y = 10
print(t.y) # prints 10! No copying was made when inserting object into dictionary.
因此,唯一關注的區域是迭代dict并在Derivatives類中插入值.這是不可避免的,除非你能以某種方式將類的內部哈希表設置為dict的內部哈希表.在純python中無法做到這一點,因為dict類是用C實現的(如上所述).
請注意,其他人建議使用生成器.這似乎也是一個好主意 – 比如你是從文件中讀取衍生物還是用簡單的公式生成它們.它會避免首先創建dict對象.但是,如果生成器只是列表(或任何其他可以包含一組值的數據結構)的包裝器,那么效率將不會有顯著的提高.
你最好的選擇是堅持你的原始方法.生成器很棒,但它們無法有效地表示一組具有一系列值(在您的場景中可能就是這種情況).用C做它也是不值得的.
編輯:畢竟,在C中做它可能是值得的!
我對Python C API的細節不太了解,但考慮在C中定義一個類,例如DerivativesBase(從dict派生).您所做的就是在C中為DerivativesBase定義一個__init__函數,它將dict作為參數并將散列表指針從dict復制到DerivativesBase對象中.然后,在python中,Derivatives類派生自DerivativesBase并實現大部分功能.
總結
以上是生活随笔為你收集整理的python定义词典_python – 自定义类是一个字典,但初始化没有字典副本?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python简笔画绘制 数据驱动绘图恐龙
- 下一篇: 用python写一个记账小程序_pyth