IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Manipulation d'un vecteur basée sur certaines valeurs de ses élements


Sujet :

Python

  1. #21
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Je ne vois pas trop l'intérêt de passer le même argument 2 fois. Je comprends que la première fois sert à sélectionner la bonne fonction, et la seconde à l'appliquer, mais quel intérêt ?
    Peut-on passer un argument différent la seconde fois ? Le fait que ça ait un sens où non dépendra de l'interprétation à donner à tout cela, mais rien dans ce qu'on sait du problème ne nous laisse supposer que cela ait un sens. Donc pourquoi introduire une couche de complexité supplémentaire, qui introduit une redondance (on doit passer l'argument 2 fois) et donc une source d'erreur potentielle ?

    Bon, là ça devient vraiment tordu mais est-ce que ceci fait ce que tu veux ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from peak.rules import when
     
    def op(L):
        pass
     
    @when(op, "L[0] == L[1]")
    def C1_op(L):
        u1, u2 = L[:2]
        def op_dispatch(op):
            raise TypeError('Unknown Operation')
     
        @when(op_dispatch, "op == 'sum'")
        def C1_sum(op):
            return lambda L: sum(L[2:]) + u1 + u2   # juste pour montrer qu'on peut utiliser u1 et u2
     
        return op_dispatch
    J'oserais jamais mettre ça dans un code réel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> l1
    [-1, -1, 1, 2, 3, 4]
    >>> l2
    [1, 2, 3, 4, 5, 6]
    >>> op(l1)('sum')(l2)
    16  # = 3 + 4 + 5 + 6 + -1 + -1
    Là on se dit que la curryfication automatique aurait du bon

  2. #22
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut


    Tu réponds toi même à la question en illustrant ses limites:
    J'oserais jamais mettre ça dans un code réel
    Quoi que... les mecs qui codent devraient pouvoir écrire en Perl/Ruby/Lisp les délires qui leur passent par la tête: s'ils livrent une boite noire qui fonctionne? Est ce qu'on ouvre son téléphone portable, sa TV, ... non on s'en sert.

    Par contre la démarche de conception doit être beaucoup plus 'white-box' car c'est ce qui va permettre de se rendre compte assez tôt qu'on a oublié ou loupé des trucs... Ce qui redonne une certaine place au 'verbeux'.
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #23
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Citation Envoyé par Wiztricks
    Pourquoi en gardes-tu la trace?
    En poussant le truc un peu, tu aurais pu écrire cela sans classes du tout
    Très juste, bon, ben pour le fun, j'ai réecris sans classe donc ^^, et en écartant l'identification de la valeur positive ou negative du "groupe", ainsi que la possibilité d'une appartenance à plusieurs "groupes" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    def vec_operate(vec):
        for x in range(3)):
            if vec_isGrp(vec,x):
                return ops[x](vec_isolate(vec))
        raise Exception('No Group identified')
     
    def vec_isGrp(lst,grp):
        '''nous dit si le vecteur appartient au groupe grp désigné'''
        grp *= 2
        return (lst[grp]==lst[grp+1]) and lst[grp] in (1,-1)
     
    def vec_isolate(lst, grp):
        grp *= 2
        return lst[0:grp]+lst[grp+2:]
     
    vec_ops =   (
                lambda lst: sum(lst),
                lambda lst: sum(lst)+5,
                lambda lst: sum(lst)/3
                )
     
    #=====================================
     
    def main():
        vecs =  (
                [1,1,42,94,67,20],
                [-1,-1,58,24,1,1]
                )
        for v in vecs:
            print vec_operate(v)
    En ce qui concerne l'utilisation de when de peak.rules, je la comprend, mais ne vois pas le besoin de son utilisation dans ce cas... Peut-être ais-je mal compris, c'est fort probable, mais en quoi est-ce plus court/clair que de simples conditions ?

  4. #24
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par N.tox Voir le message
    Très juste, bon, ben pour le fun, j'ai réecris sans classe donc ^^, et en écartant l'identification de la valeur positive ou negative du "groupe", ainsi que la possibilité d'une appartenance à plusieurs "groupes" :
    Très joli

    mais je ne pense pas que cela respecte:
    r = op(type(L))(op_name)(L)

    En ce qui concerne l'utilisation de when de peak.rules, je la comprend, mais ne vois pas le besoin de son utilisation dans ce cas... Peut-être ais-je mal compris, c'est fort probable, mais en quoi est-ce plus court/clair que de simples conditions ?
    J'aime bien la solution "peak.rules" parce que la spécialisation est calculée au fur et à mesure qu'on descend dans la précision. Votre solution fait la même chose d'ailleurs.

    Pourquoi la forme:
    r = op(type(L))(op_name)(L)
    a de l'importance (à mes yeux)?

    Parce que:
    1. elle synthétise le problème à résoudre: appliquer une opération op_name dépendant du type de Liste sur les valeurs de la Liste.
    2. le triplet (type, op_name, valeurs) "ramasse" bien les différentes "variables" sur lesquelles appliquer "op"

    Oui et alors? Elle donne un indicateur de complexité.
    Avec 3 types et 1 opération par type (sum), bof... 3 haricots qui se courent après bof... même pas peur...

    Avec 10 types et 10 opérations par type çà grimpe à 100...
    Ouch!!! La question qui se pose alors est "quelle design va permettra de réaliser (coder, tester, maintenir) tout çà sans rien oublier et en écrivant le moins de lignes... "classes"? "foncteurs"? "décorateurs"?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #25
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Avec 10 types et 10 opérations par type çà grimpe à 100...
    Ouch!!! La question qui se pose alors est "quelle design va permettra de réaliser (coder, tester, maintenir) tout çà sans rien oublier et en écrivant le moins de lignes... "classes"? "foncteurs"? "décorateurs"?
    - W
    Cela va dépendre aussi de la possibilité de "factoriser" les opérations, je suppose. En général, si on a 10 types avec 10 opérations, il est probable qu'une partie au moins des opérations soit commune à plusieurs types. Ou que certaines opérations soient décomposables en une partie commune à plusieurs types (voir tous) et une partie spécialisée.

    Si la façon de réaliser l'opération ne dépend que du type d'un seul argument, l'approche orientée object (single-dispatch) est sans doute la plus directe. On a un peu de souplesse du fait qu'on peut créer des types pour les besoins de la conception. Par exemple, même si conceptuellement on n'a qu'un seul type (qui correspond par exemple à la liste des 6 entiers), on peut créer des sous-types en fonction des valeurs qui sont dans la liste, comme le proposait wiztricks dans sa première réponse (il se peut bien sûr que ces types aient droit de séjour au niveau conceptuel aussi...).

    Si maintenant la façon de réaliser l'opération dépend du type de plusieurs arguments, il existe des design patterns pour gérer cela dans le cadre de l'orienté object single-dispatch, mais dans ce cas le multiple-dispatch, comme les "multimethods" de Common Lisp par exemple, semble plus adapté. peak.rules permet d'implémenter cela en Python, mais il y a d'autres solutions également.

    peak.rules permet d'aller encore plus loin, ce qu'ils appellent des "fonctions génériques", où la fonction a exécuter peut dépendre non seulement du types de arguments, mais de leur valeur (comme l'illustre mes deux bouts de code).

    Je me demande dans quelle mesure le fait que ces techniques ne soient pas "mainstream" ne vient pas d'un manque de support méthodologique...

  6. #26
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Hmmm... après plusieurs relectures en gardant en tête le "10 types avec 10 fun c pour chaque"

    Je comprend largement mieux ton (votre ? Tutoyons-nous, please ^^) choix des classes avec toutes les mécaniques d'héritage et de surcharge... et finalement, de mon point de vue de débutant (3 ans amateur, c'est encore débutant ), cela m'apparait comme la solution la plus facilement maintenable... oui, les décorateur me demande une gymnastique mentale plus grande que les classes ...

    Ce qui me chagrine avec ta formule
    r = op(type(L))(op_name)(L)
    c'est que "op(type(L))" retourne une fonction que l'on appelle via "(op_name)" qui retourne elle-même une fonction que l'on appelle via "(L)" pour enfin obtenir le résultat voulu... j'ai bien compris ?
    Si c'est bien ça, cela me parait bien complexe pour une problématique de simple identification... peut-être cette impression évoluera-t-elle avec l'expérience...

    Enfin je dis ça mais cela ne m'a pas empêcher de produire un autre code basé sur une classe (avant la relecture), où le "type" du vecteur est en fait un entier (où binairement le dernier bit est un positive flag, et le nombre sans le dernier bit, le "groupe") :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    class metatuple(type):
        '''metaclass permettant d'utiliser la clarté et la propreté syntaxique d'une classe
        pour obtenir un tuple constitué de fonctions complexes (multi-lignes), ordonnées'''
        def __new__(cls,nm,bs,at):
            return tuple( (v for n,v in sorted(at.items()) if n[0]=='f' ]) )
     
    class Vec(object):
        def __init__(s,v):
            s.val   = v
            s.type  = s.id(v)
     
        def id(s,v,totalGroups=3):
            '''doit nous retourner un nombre nous renseignant a la fois sur le groupe du vecteur, ainsi que sur sa "polarite", lecture binaire'''
            for x in range(totalGroups):
                x,g = x*2,x
                if (v[x]==v[x+1]) and (v[x] in (1,-1)):
                    return ( g << 1 )  +  ( v[x]==1 )
            raise Exception('Vector not identified')
     
        def op(s,*args):
            return s.ops[s.type](*args)
     
        class ops(object):
            __metaclass__=metatuple
            def f0(): print 'group:0 neg' 
            def f1(): print 'group:0 pos' 
            def f2(): print 'group:1 neg'
            def f3(): print 'group:1 pos' 
            def f4(): print 'group:2 neg'
            def f5(): print 'group:2 pos' 
     
    #======================================
     
    def main():
        Vec([1,1,42,94,67,20]).op()
        Vec([-1,-1,58,24,1,1]).op()
     
    main()
    De vos points de vue, est-ce se compliquer la vie ? est-ce lisible ?
    Et quelle sont vos suggestions/critiques/remarques ?

  7. #27
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut

    Bah lisible... Z'ont qu'à apprendre.
    J'ai passé un peu de temps à jouer avec.
    Et je l'ai substantiellement modifié...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    def get_id(v,totalGroups=3):
        '''doit nous retourner un nombre nous renseignant a la fois sur le groupe du vecteur, ainsi que sur sa "polarite", lecture binaire'''
        for x in range(totalGroups):
            x*=2
            if (v[x]==v[x+1]) and (v[x] in (1,-1)):
                return ((x/2)<<1)+int(v[x]==1)
        raise Exception('Vector not identified')
     
    def s1(self, L): return sum(L[-4:])
    def s3(self, L): return sum(L[-2:] + L[:2])
    def s5(self, L): return sum(L[:4])
     
    class Somme(object):
     
            f0 = s1
            f1 = s1
            f2 = s3
            f3 = s3
            f4 = s5
            f5 = s5
     
    class Vec(object):
        _instances = {}
        _operations = dict(
                somme = Somme(),
                )
     
        def __new__(cls, L):
            type_ = get_id(L)
            if type_ not in cls._instances:
                instance = object.__new__(cls)
                setattr(instance, 'type', type_)
                cls._instances[type_] = instance
            return cls._instances[type_]
     
     
        def __call__(self, opname):
            return getattr(self._operations[opname], 'f%d' % self.type)
     
     
    #======================================
     
    def main():
        L = [1,1,42,94,67,20]
        print Vec(L)('somme')(L)
        L = [-1,-1,58,24,1,1]
        print Vec(L)('somme')(L)
     
    main()
    Les grosses différences sont que je ne crée qu'un Vec par type et que pour avoir f(L)(opname)(L), je suis passé par __call__
    Mais ca revient au même: classifier/dispatcher/pythoniser
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #28
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut

    Ouiiiiii... le couillon ! Je comprend mieux ta formule... j'étais arrivé dans mon dernier code à la même chose... sauf que l'appel du "type" d'operation via une chaine en tant que paramètre, permet une meilleure dynamisation éventuelle, donc souplesse et évolution...

    J'adore cette structure (est-elle la "meilleure" ?... je me poserais la question plus tard, pour l'heure, je dois partir)

Discussions similaires

  1. Enumération : recherche sur base de la valeur
    Par crawling5 dans le forum Langage
    Réponses: 7
    Dernier message: 21/09/2018, 17h17
  2. [XL-2003] Requette SQL basée sur la valeur d'une cellule
    Par Tsade9 dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 24/10/2011, 10h57
  3. Mise à jour basée sur certains champs bien déterminés
    Par ToniConti dans le forum Pentaho
    Réponses: 4
    Dernier message: 06/04/2010, 16h08
  4. requete SQL basée sur une valeur d'un edit
    Par imeneimene dans le forum Bases de données
    Réponses: 2
    Dernier message: 11/06/2009, 08h54
  5. Progress bar basée sur une valeur
    Par Norin dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 11/02/2008, 16h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo