2015-02-24 57 views
0

我想創建一堆對象,以非相同的方式進行交互(神經人口模擬) - 因此一個對象可能會連接到2個其他對象和一些外部變量,另一個將連接到另一個對象和它本身等等等等。python:如何創建對象之間的交互 ​​- 參考對象似乎並不工作

我很新的面向對象的東西。我的做法是有我的課有一個列表中的所有,已與其他對象(我會想加起來在某些時候所有的連接)的連接self.connections=[]和方法:

def addNewConnection(self,strength,source,name): 
    newConnection=Connection(strength,source,name) # named tuple or class 
    self.connections.append(newConnection) 

然後在仿真的每個時間步驟i可以從所有不同來源的計算淨輸入:

netInput+=[c.source * c.weight for c in self.connections] 

,但我不能找出如何在源傳遞作爲參考,而不是一個值!因爲這些值很可能隨着模擬的進展而改變。我的猜測是做一些可重複使用的類型,比如將源代碼的值設置爲1元素列表......但這不是計算上的昂貴代碼?編輯:也不起作用。

+0

你將不得不決定何時無論如何重新計算'netInput'。沒有辦法讓'netInput'改變,因爲任何'c.source'值都會改變(即使它們是,每次改變值都會浪費時間進行重新計算:當所有的值都改變時'c.source'的值已經改變 – 2015-02-24 18:56:31

+0

_「我無法弄清楚如何將源代碼作爲參考傳遞,而不是一個值」_。參數總是被引用傳遞,確實是'def frob(x) :x = whatever'不會修改函數外的'x'的值,但這更多的是賦值的錯誤,而不是函數調用。你在「通過一種可變類型」的想法中走在正確的軌道上。我不認爲一個元素列表比一個整數要貴得多。 – Kevin 2015-02-24 18:58:09

+0

嘗試創建一個簡短的自包含示例,顯示您遇到問題時的行爲。也就是說,創建一個虛擬的「源代碼」和一個簡單的函數,並顯示您正在嘗試執行的操作,因爲您提到的參考/值問題而不起作用。對一個特定的例子比對一般的描述更容易。 – BrenBarn 2015-02-24 18:59:35

回答

0
from collections import namedtuple 

Connection=namedtuple("Connection",["source","strength"]) 
class Unit(object): 

# these first two methods just let me set up units and connections: 
    def __init__(self,par=1, response=[0], connections=[]): 
     self.par=par 
     self.response=response 
     self.connections=dict()#[] 

    def receiveConnection(self,source,strength,label): 
     # source is some other variable, strength is probably fixed but 
     # i'd like it to be able to change, too 
     #cx = Connection(label,source,strength) 
     #self.connections.append(cx) 
     self.connections[label]=Connection(source,strength) 

# stuff that gets done iteratively through the sim  
    def update(self): 
     netInput=0. 
     # based on the value of all the sources and weights right now, 
     for item in self.connections.itervalues(): 
      netInput+= item.source[0] * item.strength 
     self.response[0] += self.par * netInput 

if __name__=="__main__": 
    Unit1 = Unit() 
    Unit2 = Unit(response=[1]) 

    Unit1.receiveConnection(source=Unit2.response,strength=.5,label="U2toU1") 
    Unit2.receiveConnection(source=Unit2.response,strength=-.5,label="negativeFeedback") 

    for t in xrange(10): 
     Unit1.update() 
     print 'Unit1: ' + str(Unit1.response) 
     Unit2.update() 
     print 'Unit2: ' + str(Unit2.response) 

這實際上似乎工作,它只是笨重所有赫克(它甚至沒有在那裏合法功能):

Unit1: [0.5] 
Unit2: [0.5] 
Unit1: [0.75] 
Unit2: [0.25] 
Unit1: [0.875] 
Unit2: [0.125] 
Unit1: [0.9375] 
Unit2: [0.0625] 
Unit1: [0.96875] 
Unit2: [0.03125] 
Unit1: [0.984375] 
Unit2: [0.015625] 
Unit1: [0.9921875] 
Unit2: [0.0078125] 
Unit1: [0.99609375] 
Unit2: [0.00390625] 
Unit1: [0.998046875] 
Unit2: [0.001953125] 
Unit1: [0.9990234375] 
Unit2: [0.0009765625] 
1

這聽起來像你想要建立的是一個圖。看一下圖庫,如Python-Graphgraph-tool來處理你的數據結構。

在此設置中,你將有兩種數據結構:

  1. 其中每個對象的是由圖中的一個節點表示的曲線圖,你的連接是圖中邊。每個節點都有一個字符串名稱來標識它所代表的對象。

  2. 將節點名稱映射到對象的字典。

該設置將允許您(相當)輕鬆地操縱複雜的數據結構,而無需重新實現已存在的代碼。看起來你已經在處理與這些對象之間的連接相關的「權重」,所以加權圖似乎是組織它們的一種自然方式。

這種方法也完全繞過了你現在的問題,因爲它會將數據結構從當前對象中抽象出來。您正在編寫的類將不必知道它們包含在哪種數據結構中。您可以編寫第二個類,其中包含字符串到對象詞典和圖形,這可以讓剩下的您的應用程序只需一個接口即可訪問整個數據結構,而無需使您的當前類過於複雜。

+0

我感謝您花時間回答。我沒有接受這個答案的原因是我想學習Python(而不是圖論),並且問了一個關於問題的問題:)當我相信你說這可能會解決我的問題時,它確實不會去關於如何使用這些工具來做到這一點。我也不能相信,通過引用彼此的屬性來讓對象彼此交互很困難 - 這個問題應該在我的特定領域之外有應用。 – steeles 2015-02-24 21:07:12

+0

您所描述的方法可以正常工作,您提到的單元素列表方法可能是您最好的選擇。但是,我試圖把你帶走,原因有兩個:1)你說你的列表嘗試不起作用,但是你沒有給我們足夠的細節來幫助你調試它。如果您分享一些代碼和更具體的錯誤消息,我們可以幫助您解決它。 2)我認爲圖表方法是一個更好的抽象,並且在長期內更易於維護。它還使您可以訪問現有代碼庫,而不必重寫遍歷算法。 – skrrgwasme 2015-02-24 21:22:47

+0

我當然很感興趣,我只是不知道如何將算法轉換成圖形。 – steeles 2015-02-24 21:49:00