2010-09-28 31 views
4

我有一個環結構來實現如下(根據菜譜食譜,我發現):Python - 如何區分指向同一對象的兩個列表元素?

class Ring(list): 

    def turn(self): 
     last = self.pop(0) 
     self.append(last) 

    def setTop(self, objectReference): 
     if objectReference not in self: 
      raise ValueError, "object is not in ring" 

     while self[0] is not objectReference: 
      self.turn() 

說我做到以下幾點:

x = Ring([1,2,3,4,4]) 
x.setTop(4) 

我的代碼將永遠設置第一個4(目前x [3])到x [0]。它似乎(通過x [3]和x [4]之間的對象標識和哈希id測試)Python正在重用這4個對象。

我如何告訴Python我真的希望第二個4(當前是x [4])在頂部?

道歉的基本問題......作爲一個自學成才的初學者的垮臺之一。

感謝,

邁克

===編輯===

對於它的價值,我放棄了從類的機頂盒方法。我已經將它添加到標準配方思考「嘿,這將是整潔,可能是有用的。」由於答案(特別是「有什麼不同」),以及我自己使用結構展示的經驗,這是一種糟糕的方法,不支持我的任何用例。

換句話說,添加的東西,因爲我可以而不是履行需要=失敗。

+0

怎麼是'機頂盒()'應該知道'4'你的意思只用'x.setTop(4)'調用?也許你只需要第二個參數來指出哪一個參數。 – martineau 2010-09-29 10:26:44

回答

4

Python入門,第4版 - 第6章:

至少在概念上,每次運行一個 表達式生成腳本中的一個新的值時,Python中創建一個新的對象(即,一塊內存)來表示 的值。在內部,作爲一種優化,Python緩存和重用某些可更改的對象,如小整數和字符串(每個0並不是真正的內存新件 - 更多關於此後的緩存行爲)。但是,從邏輯的角度來看,它的作用就好像每個表達式的結果值是一個獨特的對象,並且每個對象都是不同的內存塊。

的問題是..

if x[3] is x[4]: 
    print "What's the difference?" 
+0

我不得不說,我四個月前第一次用python開始時,我在書店裏急着買了一個學習python。這完全浪費時間。它只是如此厚重,因爲它重複了一切_ad。 nauseum_,然後仍然錯過了一半的說。簡而言之Python是更好的。它一切都說得很好。 – aaronasterling 2010-09-28 17:04:55

+0

更多關於主題,在這種情況下的區別是模型環的旋轉狀態。 – aaronasterling 2010-09-28 17:52:35

+0

當然,但是如果環中有兩個基本常量,基於這些文字之間關係的建模環的旋轉狀態是沒有意義的。誰在乎是否抓住了那個常數或第二個的第一個參考?由於它們具有相同的屬性,因此沒有真正的區別。如果一個人擁有不同的物體,python的反射工具會顯示它們之間的差異,從而允許在模擬環中出現明顯的差異。如果我給你一支標有「4」字的棍子,並且說「從4開始到另一端」,那麼你選擇哪個4? – sleepynate 2010-09-28 21:36:46

0

我也無法確定,但我猜數字,即使是beeing對象,在您的代碼的不同點使用相同的對象。 我爲什麼這麼認爲? Look:

>>> type(2) 
<type 'int'> 
>>> type(lambda x:x) 
<type 'function'> 
>>> 2 is 2 
True 
>>> (lambda x: x) is (lambda x: x) 
False 

2個對象在創建兩次時不相同。但數字不是由你創造的,他們已經在那裏。將一個4與另一個4區別開來是沒有意義的。至少我沒有看到一個。

+0

在進行這種比較時,您想使用'is'運算符。 – aaronasterling 2010-09-28 17:53:56

+0

@AaronMcSmooth謝謝你指出。當我寫這篇文章時已經很晚了。 – erikbwork 2010-09-29 00:12:06

2

如果你知道你想要第二個,然後做

x = Ring([1,2,3,4,4]) 
x.setTop(4) 
x.turn() 
x.setTop(4) 

可以提高機頂盒()採取額外的參數,並做內。

0

對於少數人來說,python會預先製作一個對象緩存以避免製作新對象的成本。他們將擁有相同的對象標識。 Java也是這樣做的。你需要一種方法來避免這樣做。

0

Python的重用小整數和短字符串。據我所知,沒有辦法解決這個問題 - 你必須與此相處,並且setTop只會旋轉,直到第一場比賽。我想你可以添加一個optinal參數n = 1,然後轉到n這個匹配。但這有點不合時宜,不是嗎?

Unrelatedly,考慮一下:

>>> class Point(object): 
...  def __init__(self, x, y): 
...   self.x, self.y = x, y 
...  def __eq__(self, other): 
...   return (self.x == other.x and self.y == other.y) 
... 
>>> a_ring = Ring(Point(1, 2), Point(15, -9), Point(0, 0)) 
>>> a_ring.seTop(Point(15, -9)) 
Traceback ... 
... 
ValueError: object not in ring 

它不是如何工作的,是嗎?你應該使用while self[0] != objectReference(這是一個令人誤解的名字)來避免這種情況。

+0

好點。我不確定我是否希望它以這種方式工作。我必須考慮一下。 – MikeRand 2010-09-28 17:03:17

1

Cpython對於較小的整數有一個「整數緩存」,因此-5到255的值(可能因版本或Python實現而異)對給定值重複使用同一個對象。也就是說,所有4都是相同值爲4的int對象。這樣做是爲了減少創建對象的必要性。

有幾種方法可以解決這個問題。

  • 您可以使用長整數(例如,寫4L而不是4)。 Python不使用長整型緩存。 (你也可以使用浮點數,因爲它們同樣沒有被緩存。)但是,如果你用數字做了很多數學運算,這可能會導致一些性能損失。
  • 您可以將每個項目包裝在一個列表或元組中(合理方便,因爲這裏有簡單的語法,雖然它比長整數或浮點數更多的語法)。
  • 您可以創建自己的對象來包裝整數。該對象將具有與整數相同的方法(因此它在數學,比較,打印等方面的工作方式類似於整數),但每個實例都是唯一的。

我個人喜歡在這種情況下使用長整數。您可以輕鬆地將整數轉換爲構造函數中的longs以及添加項目的任何方法。

1

聽起來像你總是想要至少轉一次,對不對?如果是這樣,重新寫你的機頂盒的方法,像這樣:

def setTop(self, objectReference): 
    if objectReference not in self: 
     raise ValueError, "object is not in ring" 

    self.turn() 
    while self[0] is not objectReference: 
     self.turn() 

然後週期的預期狀態之間:

>>> x = Ring([1,2,3,4,4]) 
>>> x 
[1, 2, 3, 4, 4] 
>>> x.setTop(4) 
>>> x 
[4, 4, 1, 2, 3] 
>>> x.setTop(4) 
>>> x 
[4, 1, 2, 3, 4] 
>>> x.setTop(4) 
>>> x 
[4, 4, 1, 2, 3] 
相關問題