2012-07-10 2 views
1

Je suis nouveau à Python. J'écris une simulation dans SimPy pour modéliser une ligne de production, qui ressemble à: Machine 1 -> Buffer 1 -> Machine 2 -> Buffer 2 -> et ainsi de suite ..Comment appeler une instance différente de la même classe en python?

Ma question: J'ai une classe , Machine, dont il existe plusieurs instances. Supposons que l'instance actuelle soit la machine 2. Les méthodes de cette instance affectent les états des machines 1 et 3. Par exemple, si la mémoire tampon 2 était vide, alors la machine 3 est inactive. Mais lorsque la Machine 2 fait partie du Buffer 2, la Machine 3 devrait être activée.

Alors, comment faire référence à différentes instances de la même classe à partir de n'importe quelle instance de cette classe? Aussi, question légèrement différente: Comment appeler un objet (Buffers 1 et 2, dans ce cas) à partir de l'instance actuelle d'une autre classe?

Éditer: Edité pour plus de clarté sur le système.

+4

Vous devez fournir plus d'informations sur la structure de votre code. Comment Machine 2 sait-elle même que les autres machines existent? – BrenBarn

+1

Ces états sont-ils partagés entre toutes les machines ou chaque machine en at-elle une individuelle? – phg

Répondre

4

Il n'est pas courant que les instances d'une classe connaissent d'autres instances de la classe.

Je vous recommande de garder une sorte de collection d'instances de votre classe elle-même, et utiliser la classe pour rechercher les instances:

class Machine(object): 
    lst = [] 
    def __init__(self, name): 
     self.name = name 
     self.id = len(Machine.lst) 
     Machine.lst.append(self) 

m0 = Machine("zero") 
m1 = Machine("one") 

print(Machine.lst[1].name) # prints "one" 
+0

Merci @steveha. C'est exactement ce que je cherchais. J'ai codé dans MATLAB, et faire quelque chose comme ça était assez facile là-bas. Avec POO, ce n'est pas aussi facile. Mais compte tenu de toutes les autres caractéristiques de la POO, pensez-vous qu'il existe de meilleurs moyens de le faire, c'est-à-dire de ne pas traduire le code MATLAB en Python? – user1509616

+0

Eh bien, comme discuté dans d'autres réponses ci-dessous, je pense que vous devriez explicitement relier les objets qui doivent être liés. Si vous utilisez la réponse de @ mgilson ou mon autre réponse, vous aurez un cadre de base sur lequel construire votre simulation; Il devrait s'agir d'un design propre et bien rangé, et la machine0 ne peut accidentellement gâcher la machine99 car elle ne sera connectée en aucune façon. – steveha

1

Maintenant que vous avez ajouté plus d'informations sur le problème, je vais suggérer une solution alternative. Une fois que vous avez créé vos machines, vous pouvez les lier ensemble.

class Machine(object): 
    def __init__(self): 
     self.handoff = None 
    def input(self, item): 
     item = do_something(item) # machine processes item 
     self.handoff(item) # machine hands off item to next machine 

m0 = Machine() 

m1 = Machine() 
m0.handoff = m1.input 

m2 = Machine() 
m1.handoff = m2.input 

def output(item): 
    print(item) 

m2.handoff = output 

Maintenant, lorsque vous appelez m0.input(item) il fera son traitement, puis la main de l'élément à m1, qui fera la même chose et à la main de m2, qui fera son traitement et appeler output(). Cet exemple montre le traitement synchrone (un élément ira tout au long de la chaîne avant que les appels de fonctions ne retournent) mais vous pouvez également demander à la méthode .input() de placer l'élément dans une file d'attente pour traitement, puis de revenir immédiatement; De cette façon, vous pourriez faire en sorte que les machines fonctionnent en parallèle.

Avec ce système, les connexions entre les machines sont explicites, et chaque machine connaît seulement celle qui la suit (celle-ci a besoin de pour en savoir plus).

J'utilise le mot «threading» pour décrire le processus de liaison entre des objets comme celui-ci. Un élément en cours de traitement suit le fil d'une machine à l'autre avant d'arriver à la sortie. C'est un peu ambigu car il n'a rien à voir avec les threads d'exécution, ce terme n'est donc pas parfait.

+0

Habituellement, je considère les choses dans ce genre de processus comme un «pipeline». À bien des égards, c'est semblable à un pipeline en coquille. – mgilson

+0

"pipeline" est bon car il ne sera pas confondu avec "threads d'exécution". J'avais l'habitude de travailler dans FORTH, et cela s'appelle parfois un "langage interprété enfilé"; J'avais l'habitude d'avoir un livre dont la couverture montrait une aiguille, avec du fil derrière elle, reliant des blocs de code. :-) – steveha

3

Ceci est un exemple idiot que je cuisinais là où vous mettez des données dans la première machine qui se déplace au premier tampon qui se déplace à la deuxième machine ...

Chaque machine balises juste la données avec son numéro d'identification et passe le long, mais vous pouvez faire les machines à faire quelque chose. Vous pouvez même enregistrer une fonction à appeler sur chaque machine lorsqu'elle reçoit des données.

class Machine(object): 
    def __init__(self,number,next=None): 
     self.number=number 
     self.register_next(next) 

    def register_next(self,next): 
     self.next=next 

    def do_work(self,data): 
     #do some work here 
     newdata='%s %d'%(str(data),self.number) 
     if(self.next is not None): 
      self.next.do_work(newdata) 

class Buffer(Machine): 
    def __init__(self,number,next=None): 
     Machine.__init__(self,number,next=next) 
     data=None 

    def do_work(self,data): 
     if(self.next is not None): 
      self.next.do_work(data) 
     else: 
      self.data=data 

#Now, create an assembly line 
assembly=[Machine(0)] 
for i in xrange(1,20): 
    machine=not i%2 
    assembly.append(Machine(i) if machine else Buffer(i)) 
    assembly[-2].register_next(assembly[-1]) 

assembly[0].do_work('foo') 
print (assembly[-1].data) 

EDIT

buffers sont maintenant des machines aussi.

+0

+1. Pour une simulation non triviale, il peut ne pas être possible d'utiliser des boucles pour connecter toutes les machines et tous les tampons; il pourrait être nécessaire de régler les choses au moins en partie à la main. Mais j'aime totalement l'approche. J'ai suggéré quelque chose comme ça mais je n'ai pas montré les deux machines et tampons; vous êtes allé le mile supplémentaire ici et a fait une réponse très complète. – steveha

+0

@steveha - À certains égards, j'aime mieux le tien (+1). Je ne suis pas sûr que j'aime 'def register_machine (self, machine)' dans le mien par exemple. ('mybuff.machine = mymachine' fonctionnerait très bien, mais quand je vois des éléments d'une machine ensemble, ça fonctionne mieux qu'une fonction dans mon esprit) ... Je ne sais pas comment l'API devrait travailler sur celui-ci. Mais de toute façon, nous pensions tous les deux la même chose. Bien sûr, vous pensiez beaucoup plus vite puisque vous avez répondu 20 minutes avant que je ne le fasse et je n'ai pas vu votre réponse avant de poster le mien;) ... – mgilson

+0

Eh bien, j'ai déjà écrit ce genre de code. J'ai tendance à utiliser le mot «filetage» pour décrire le processus de les relier entre eux; ceci pourrait s'appeler une "simulation filetée" peut-être. – steveha

Questions connexes