Question

J'écris un programme qui utilise des techniques génétiques pour évoluer équations. Je veux être en mesure de présenter la fonction « mainfunc » au Python parallèle « submit » fonction. La fonction « mainfunc » appelle deux ou trois méthodes définies dans la classe utilitaire. Ils instancier d'autres classes et appellent différentes méthodes. Je pense que ce que je veux est tout cela dans un espace de nommage. J'ai donc instancié certains (peut-être devrait être tous) des classes à l'intérieur de la fonction « mainfunc ». J'appelle la méthode utilitaire « générer () ». Si nous devions suivre est la chaîne d'exécution il impliquerait toutes les classes et méthodes dans le code.

Maintenant, les équations sont stockées dans un arbre. Chaque fois qu'un arbre est généré, muté ou croix élevés, les nœuds doivent donner une nouvelle clé afin qu'ils puissent être accessibles à partir d'un attribut dictionnaire de l'arbre. La classe « suite_de_touches » génère ces clés.

En Python parallèle, je vais envoyer plusieurs instances de « mainfunc » à la fonction « Soumettre » du PP. Chacun doit pouvoir accéder « suite_de_touches ». Ce serait bien si tous accédé à la même instance de suite_de_touches de sorte qu'aucun des noeuds sur les arbres en retour avaient la même clé, mais je ne pouvais contourner que si nécessaire.

: ma question porte sur la farce tout dans mainfunc. Merci (Edit) Si je ne comprends pas tout à mainfunc, je dois essayer de dire PP sur les fonctions dépendantes, etc. en passant divers arguements en divers endroits. J'essaie d'éviter cela.

(fin Edit) si ks.next () est appelée dans la « générer () fonction, il renvoie l'erreur 'NameError: nom global 'ks' est pas défini'

class KeySeq:
    "Iterator to produce sequential \
    integers for keys in dict"
    def __init__(self, data = 0):
        self.data = data
    def __iter__(self):
        return self
    def next(self):
        self.data = self.data + 1
        return self.data
class One:
    'some code'
class Two:
    'some code'
class Three:
    'some code'
class Utilities:
    def generate(x):
        '___________'
    def obfiscate(y):
        '___________'
    def ruminate(z):
        '__________'


def mainfunc(z):
    ks = KeySeq()
    one = One()
    two = Two()
    three = Three()
    utilities = Utilities()
    list_of_interest = utilities.generate(5)
    return list_of_interest

result = mainfunc(params)
Était-ce utile?

La solution

Si vous voulez que tous les cas de mainfunc d'utiliser le même objet KeySeq, vous pouvez utiliser l'astuce de la valeur du paramètre par défaut:

def mainfunc(ks=KeySeq()):
   key = ks.next()

Tant que vous ne passez pas réellement une valeur de ks, tous les appels à mainfunc utilisera l'instance de KeySeq qui a été créé lorsque la fonction a été définie.

Voici pourquoi, si vous ne connaissez pas: Une fonction est un objet. Il a des attributs. L'un de ses attributs est nommé func_defaults; il est un tuple contenant les valeurs par défaut de tous les arguments de sa signature des valeurs par défaut. Lorsque vous appelez une fonction et ne fournissez pas de valeur pour un argument qui a une valeur par défaut, la fonction récupère la valeur de func_defaults. Donc, lorsque vous appelez mainfunc sans fournir une valeur pour ks, il obtient l'instance KeySeq() de la tuple func_defaults. Ce qui, pour cette instance de mainfunc, est toujours la même instance KeySeq.

Maintenant, vous dites que vous allez envoyer « plusieurs instances de mainfunc à la fonction submit du PP. » Voulez-vous dire vraiment plusieurs instances? Si oui, le mécanisme que je décris ne fonctionnera pas.

Mais il est difficile de créer plusieurs instances d'une fonction (et le code que vous avez posté ne fonctionne pas). Par exemple, cette fonction ne retourne une nouvelle instance de g chaque fois qu'il est appelé:

>>> def f():
        def g(x=[]):
            return x
        return g
>>> g1 = f()
>>> g2 = f()
>>> g1().append('a')
>>> g2().append('b')
>>> g1()
['a']
>>> g2()
['b']

Si je l'appelle g() sans argument, elle renvoie la valeur par défaut (d'abord une liste vide) de son tuple func_defaults. Depuis g1 et g2 sont différentes instances de la fonction g, leur valeur par défaut pour l'argument x est aussi une autre instance que le montre ci-dessus.

Si vous souhaitez rendre plus explicite que d'utiliser un délicat effet secondaire des valeurs par défaut, voici une autre façon de le faire:

def mainfunc ():       sinon hasattr (mainfunc, "ks"):           setattr (mainfunc, "ks", suite_de_touches ())       key = mainfunc.ks.next ()

Enfin, un point super important que le code que vous avez posté belvédères: Si vous allez faire un traitement parallèle des données partagées, le code qui touche qui a besoin de données pour mettre en œuvre le verrouillage. Regardez l'exemple de callback.py dans la documentation Python parallèle et voir comment le verrouillage est utilisé dans la classe Sum, et pourquoi.

Autres conseils

Il est bien de structurer votre programme de cette façon. Beaucoup d'utilitaires en ligne de commande suivent le même schéma:

#imports, utilities, other functions

def main(arg):
    #...

if __name__ == '__main__':
    import sys
    main(sys.argv[1])

De cette façon, vous pouvez appeler la fonction main d'un autre module en importer, ou vous pouvez l'exécuter à partir de la ligne de commande.

Votre concept de classes en Python est pas sain, je pense. Peut-être, ce serait une bonne idée de revoir les bases. Ce lien vous aidera.

Principes de base Python - Classes

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top