2015-02-24 56 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