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 :

Fonction "is iterable" et introspection


Sujet :

Python

  1. #1
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut Fonction "is iterable" et introspection
    Bonjour à tous !

    Question simple :
    Y a-t-il un moyen de demander à un objet si il est iterable ?
    Il y a bien callable, pourquoi pas iterable ?

    Petite question subsidiaire : pourquoi certains objets ont un nom (attribut __name__) et d'autres pas ?

    Le but ultime de tout ça, c'est d'écrire une fonction DeepPrint qui affiche recursivement tous les membres d'un objet.

    Le but ultime du but ultime, c'est d'écrire une fonction DeepCompare qui compare 2 instances, membre par membre, recursivement.

  2. #2
    Membre émérite
    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
    Par défaut
    Question simple :
    Y a-t-il un moyen de demander à un objet si il est iterable ?
    Il y a bien callable, pourquoi pas iterable ?
    Il faut vérifier la présence de la méthode __iter__, si non, vérifier la présence de la méthode __getitem__, où __getitem__ accepterait comme valeur de clé, des ints partant de 0.

    ou bien faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    try:
        iter(obj)
        isiterable=1
    except:
        isiterable=0
    Petite question subsidiaire : pourquoi certains objets ont un nom (attribut __name__) et d'autres pas ?
    Sûrement parce que certaines classes / fonctions ont été écrites en C et n'incluaient pas cet attribut.


    Le but ultime de tout ça, c'est d'écrire une fonction DeepPrint qui affiche recursivement tous les membres d'un objet.
    C'est marrant ça, j'me suis ammuser à faire un truc un peu similaire cette nuit, je sais pas si ça pourra t'être utile... (ou plutôt être utile tout court...)
    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
    def moduleAnalyser(module):
        for e in dir(module):
            tp=str(type(eval('%s.%s'%(module.__name__,e))))
            if 'func' in tp:
                yield module.__name__+'.'+e, 'f'
            elif "'type'>" in tp:
                yield module.__name__+'.'+e, 'c'
                for i in classAnalyser(eval('%s.%s'%(module.__name__,e))):
                    yield '%s.%s'%(module.__name__,i[0]),i[1]
            elif 'class' in tp:
                yield module.__name__+'.'+e, 'ci: %s'%eval('module.%s.__class__'%e)
                for i in classAnalyser(eval('module.%s.__class__'%e)):
                    yield module.__name__+'.'+i[0], i[1]
            else:
                yield module.__name__+'.'+e, 'v'
     
    def classAnalyser(cls):
        for e in dir(cls()):
            tp=str(type(eval('cls().%s'%(e))))
            if e!='__class__':
                if 'func' in tp:
                    yield cls.__name__+'().'+e, 'f'
                elif "'type'>" in tp:
                    yield cls.__name__+'().'+e, 'c'
                    for i in classAnalyser(eval('cls().%s'%e)):
                        yield '%s.%s'%(cls.__name__+'()', i[0]), i[1]
                elif 'method' in tp:
                    yield cls.__name__+'().'+e, 'm'
                elif 'class' in tp:
                    yield cls.__name__+'().'+e, 'ci: %s'%eval('cls().%s.__class__'%e)
                    for i in classAnalyser(eval('cls().%s.__class__'%e)):
                        yield cls.__name__+'().'+i[0], i[1]
                else:
                    yield cls.__name__+'().'+e, 'a'

  3. #3
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Merci pour tes réponses !

    J'ai essayé ta fonction classAnalyser avec ces petites classes là :
    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
    class TestSubClass:
        def __init__(self,i):
            self.s0 = 'hello'+str(i)
            self.i0 = i
            self.d0 = i/3.0
            self.l0 = [ i+1,i+2.0,str( i+3 )]
     
    class TestClass:
        def __init__(self):
            self.s = 'hello'
            self.i = 321
            self.d = 3.14159
            self.l = [ 1,2.345,'world !',TestSubClass(100)]
            self.c = TestSubClass(200)
     
    for i in classAnalyser( TestClass ) : print i
    et j'obtiens ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ('TestClass().__doc__', 'a')
    ('TestClass().__init__', 'm')
    ('TestClass().__module__', 'a')
    ('TestClass().c', 'a')
    ('TestClass().d', 'a')
    ('TestClass().i', 'a')
    ('TestClass().l', 'a')
    ('TestClass().s', 'a')
    Je n'ai pas l'impression qu'il visite récursivement les sous objets de ma classe.
    J'ai raté quelque chose ?

    D'autre part, à propos de l'attribut __name__, je ne suis pas sûr qu'il y ait un rapport avec l'implémentation C parce que même mes classes en pur python n'en ont pas...

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Hello,

    J’ai trouvé isSequenceType(o) dans le module operator.

    Mais je ne comprends pas tout du commentaire:


    isSequenceType(o)

    Returns true if the object o supports the sequence protocol. This returns true for all objects which define sequence methods in C, and for all instance objects defining __getitem__. Warning: There is no reliable way to test if an instance supports the complete sequence interface since the interface itself is ill-defined. This makes this test less useful than it otherwise might be.

    Quelques essais
    sur une chaîne, une liste, un tuple, ça renvoie True
    sur un entier, sur enumerate(), sur un générateur, ça renvoie False

  5. #5
    Membre émérite
    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
    Par défaut
    D'autre part, à propos de l'attribut __name__, je ne suis pas sûr qu'il y ait un rapport avec l'implémentation C parce que même mes classes en pur python n'en ont pas...
    Alors ça doit être parce que ce ne sont pas des new-style class (héritant d'object ou autre classes dérivant de cette dernière)

    EDIT : de toute façon c'est vachement bancal en fait, à moins de définir que des paramètres par défaut pour __init__, et encore... y'a de grosses limitations :
    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
    class TestSubClass(object):
        def __init__(self,i):
            self.s0 = 'hello'+str(i)
            self.i0 = i
            self.d0 = i/3.0
            self.l0 = [ i+1,i+2.0,str( i+3 )]
     
    class TestClass(object):
        def __init__(self):
            self.s = 'hello'
            self.i = 321
            self.d = 3.14159
            self.l = [ 1,2.345,'world !',TestSubClass(100)]
            self.c = TestSubClass(200)
     
    for i in classAnalyser( TestClass ) : print i
    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
    ('TestClass().__delattr__', 'm')
    ('TestClass().__dict__', 'a')
    ('TestClass().__doc__', 'a')
    ('TestClass().__format__', 'f')
    ('TestClass().__getattribute__', 'm')
    ('TestClass().__hash__', 'm')
    ('TestClass().__init__', 'm')
    ('TestClass().__module__', 'a')
    ('TestClass().__new__', 'f')
    ('TestClass().__reduce__', 'f')
    ('TestClass().__reduce_ex__', 'f')
    ('TestClass().__repr__', 'm')
    ('TestClass().__setattr__', 'm')
    ('TestClass().__sizeof__', 'f')
    ('TestClass().__str__', 'm')
    ('TestClass().__subclasshook__', 'f')
    ('TestClass().__weakref__', 'a')
    ('TestClass().c', "ci: <class '__main__.TestSubClass'>")
     
    Traceback (most recent call last):
      File "C:/Documents and Settings/N.tox/Bureau/t.py", line 35, in <module>
        for i in classAnalyser( TestClass ) : print i
      File "C:/Documents and Settings/N.tox/Bureau/t.py", line 15, in classAnalyser
        for i in classAnalyser(eval('cls().%s.__class__'%e)):
      File "C:/Documents and Settings/N.tox/Bureau/t.py", line 2, in classAnalyser
        for e in dir(cls()):
    TypeError: __init__() takes exactly 2 arguments (1 given)
    avec paramètre par défaut:
    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
    class TestSubClass(object):
        def __init__(self,i=0):
            self.s0 = 'hello'+str(i)
            self.i0 = i
            self.d0 = i/3.0
            self.l0 = [ i+1,i+2.0,str( i+3 )]
     
    class TestClass(object):
        def __init__(self):
            self.s = 'hello'
            self.i = 321
            self.d = 3.14159
            self.l = [ 1,2.345,'world !',TestSubClass(100)]
            self.c = TestSubClass(200)
     
    for i in classAnalyser( TestClass ) : print i
    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
    ('TestClass().__delattr__', 'm')
    ('TestClass().__dict__', 'a')
    ('TestClass().__doc__', 'a')
    ('TestClass().__format__', 'f')
    ('TestClass().__getattribute__', 'm')
    ('TestClass().__hash__', 'm')
    ('TestClass().__init__', 'm')
    ('TestClass().__module__', 'a')
    ('TestClass().__new__', 'f')
    ('TestClass().__reduce__', 'f')
    ('TestClass().__reduce_ex__', 'f')
    ('TestClass().__repr__', 'm')
    ('TestClass().__setattr__', 'm')
    ('TestClass().__sizeof__', 'f')
    ('TestClass().__str__', 'm')
    ('TestClass().__subclasshook__', 'f')
    ('TestClass().__weakref__', 'a')
    ('TestClass().c', "ci: <class '__main__.TestSubClass'>")
    ('TestClass().TestSubClass().__delattr__', 'm')
    ('TestClass().TestSubClass().__dict__', 'a')
    ('TestClass().TestSubClass().__doc__', 'a')
    ('TestClass().TestSubClass().__format__', 'f')
    ('TestClass().TestSubClass().__getattribute__', 'm')
    ('TestClass().TestSubClass().__hash__', 'm')
    ('TestClass().TestSubClass().__init__', 'm')
    ('TestClass().TestSubClass().__module__', 'a')
    ('TestClass().TestSubClass().__new__', 'f')
    ('TestClass().TestSubClass().__reduce__', 'f')
    ('TestClass().TestSubClass().__reduce_ex__', 'f')
    ('TestClass().TestSubClass().__repr__', 'm')
    ('TestClass().TestSubClass().__setattr__', 'm')
    ('TestClass().TestSubClass().__sizeof__', 'f')
    ('TestClass().TestSubClass().__str__', 'm')
    ('TestClass().TestSubClass().__subclasshook__', 'f')
    ('TestClass().TestSubClass().__weakref__', 'a')
    ('TestClass().TestSubClass().d0', 'a')
    ('TestClass().TestSubClass().i0', 'a')
    ('TestClass().TestSubClass().l0', 'a')
    ('TestClass().TestSubClass().s0', 'a')
    ('TestClass().d', 'a')
    ('TestClass().i', 'a')
    ('TestClass().l', 'a')
    ('TestClass().s', 'a')
    le plus relou, c'est que je me souviens même plus pourquoi j'avais créer ces fonctions... faut qu'j'arrête la boisson moi...

  6. #6
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Finalement, j'ai à peu près réussi à coder la fonction que je voulais.
    Ce qui est rigolo, c'est qu'on ne retombe pas du tout sur la même approche...
    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
    def iterable ( obj ):
        try    : iter( obj )
        except : return False
        return True
     
    def DeepPrint ( a,name='',indent=0 ):
        if hasattr( a,'__dict__' ):
            for i in a.__dict__.items():
                n,e,v = i[0],getattr( a,i[0] ),i[1]
                if not isinstance( e,basestring ) and iterable( e ):
                    print ' '*indent,n,type( e ),':'
                    for i in e :
                        DeepPrint( i,'',indent+4 )
                elif hasattr( e,'__dict__' ):
                    print ' '*indent,n,type( e )
                    DeepPrint( e,n,indent+4 )
                else:
                    print ' '*indent,n,type( e ),str( v )
        elif hasattr( a,'__name__'):
            print ' '*indent,a.__name__,type( a ),str( a )
        else:
            print ' '*indent,name,type( a ),str( a )
    Dis moi ce que tu en penses...

    Pour revenir à l'attribut __name__, je n'ai aucune new-style class dans mon code...

  7. #7
    Membre émérite
    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
    Par défaut
    Hmmm, je vois quelque petites couilles :
    ¤ __dict__ est très bien tant que l'objetn'a pas d'attribut __slots__; dir() s'en fout
    ¤ <c>" n,e,v = i[0],getattr( a,i[0] ),i[1] "</c> veulent dirent la même chose, autant supprimer le getattr()
    ¤ à un moment tu évoque "basestring", mais je ne vois pas la définition de ce dernier dans ton code
    ¤ une class et son instance n'ont pas forcément le même __dict__, puisque souvent, certains attributs sont définis depuis __init__

    Voilà, hormis ces petits détails, c'est une approche bien plus visuelle... Que dire de plus ?

    Pour continuer à propos de __name__, même dans une old-style class, __name__ est présent, il échappe simplement à dir() et à __dict__ (d'ailleurs ce dernier aussi échappe à dir()...)

  8. #8
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 045
    Par défaut
    Le but ultime de tout ça, c'est d'écrire une fonction DeepPrint qui affiche recursivement tous les membres d'un objet.
    Pourquoi ne pas faire selon cet exemple, où l'on rend iterable un objet?

    Objet iterable

  9. #9
    Membre émérite
    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
    Par défaut
    Ben si j'ai bien compris, le but n'est pas de rendre un objet iterable, mais de reconnaître (entre autres) un objet iterable d'un non iterable, de façon à explorer l'objet iterable et en retourner les valeurs (pour un liste par exemple).

  10. #10
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 045
    Par défaut
    Pour tester si un objet est itérable

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> a=["e", [1, 2, 3], (1, 2)]
    >>> for obj in a:
    ...     getattr(obj, '__iter__', False)
    ...
    Résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    False
    <method-wrapper '__iter__' of list object at 0x924f76c>
    <method-wrapper '__iter__' of tuple object at 0x91f280c>
    On peut aussi creer une fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> isiterable=lambda obj:isinstance (obj, basestring)
    >>> for obj in a:
    ...     isiterable(obj)
    ... 
    True
    False
    False

  11. #11
    Membre émérite
    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
    Par défaut
    iter(o[, sentinel])
    Return an iterator object. The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, o must be a collection object which supports the iteration protocol (the __iter__() method), or it must support the sequence protocol (the __getitem__() method with integer arguments starting at 0). If it does not support either of those protocols, TypeError is raised. If the second argument, sentinel, is given, then o must be a callable object. The iterator created in this case will call o with no arguments for each call to its next() method; if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned.

    New in version 2.2.

  12. #12
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Citation Envoyé par N.tox Voir le message
    Hmmm, je vois quelque petites couilles :
    ¤ __dict__ est très bien tant que l'objetn'a pas d'attribut __slots__; dir() s'en fout
    J'avais opté pour __dict__ plutôt que dir parce que ce dernier me renvoie aussi les attributs automatiquement générés par python et pas seulement ceux créés par moi.
    Si j'utilise dir(), comment faire le distingo ?
    Citation Envoyé par N.tox Voir le message
    ¤ <c>" n,e,v = i[0],getattr( a,i[0] ),i[1] "</c> veulent dirent la même chose, autant supprimer le getattr()
    Tu as raison ! Je croyais que i[1] était uniquement la représentation string de la valeur de l'attribut et non l'attribut lui même.
    Citation Envoyé par N.tox Voir le message
    ¤ à un moment tu évoque "basestring", mais je ne vois pas la définition de ce dernier dans ton code
    basestring est un type natif du langage : c'est l'ancêtre commun à string et unicode.

  13. #13
    Membre émérite
    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
    Par défaut
    Citation Envoyé par sopsag Voir le message
    J'avais opté pour __dict__ plutôt que dir parce que ce dernier me renvoie aussi les attributs automatiquement générés par python et pas seulement ceux créés par moi.
    Si j'utilise dir(), comment faire le distingo ?
    Automatiquement généré par python ? Comme __dict__, __sizeof__, __reduce__ & cie ? Si c'est bien de ça que tu parle, dir s'en occupe très bien (voir message #5), non ?

    Ou bien est-ce encore d'autre attributs ? Si oui, pourrais-tu me donner un exemple ?

  14. #14
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tt = TestClass()
    print dir( tt )
    print tt.__dict__.keys()
    me donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ['__doc__', '__init__', '__module__', 'c', 'd', 'i', 'l', 's']
    ['i', 'c', 's', 'd', 'l']
    On voit bien que dir me ramène aussi __doc__, __init__ et __module__. Or ce que je veux c'est juste mes membres : c, d, i, l et s.
    En fait, c'est même pire que ça !
    Regarde cet exemple tout bête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> i = 54
    >>> dir( i )
    ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__','__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
    Là je trouve qu'il abuse un peu...
    Donc, __dict__ a l'air d'être ce qu'il me faut, non ? Même si ça m'oblige à tester son existence...
    D'ailleurs voici ma dernière version
    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
    def iterable ( obj ):
        return getattr( obj,'__iter__',-1 ) != -1
     
    def DeepPrint ( param,name='',indent=0 ):
        name = getattr( param,'__name__',name )
        if hasattr( param,'__dict__' ):
            print ' '*indent,name,type( param ),':'
            for item in param.__dict__.items():
                DeepPrint( item[1],item[0],indent+4 )
        elif iterable( param ):
            print ' '*indent,name,type( param ),':'
            for item in param:
                DeepPrint( item,'-',indent+4 )
        else:
            if isinstance( param,basestring ) :
                print ' '*indent,name,type( param ),'"%s"'%param
            else:
                print ' '*indent,name,type( param ),param
    et là j'obtiens exactement ce que j'espérais :
    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
      <type 'instance'> :
         i <type 'int'> 321
         c <type 'instance'> :
             i0 <type 'int'> 200
             s0 <type 'str'> "hello200"
             l0 <type 'list'> :
                 - <type 'int'> 201
                 - <type 'float'> 202.0
                 - <type 'str'> "203"
             d0 <type 'float'> 66.6666666667
         s <type 'str'> "hello"
         d <type 'float'> 3.14159
         l <type 'list'> :
             - <type 'int'> 1
             - <type 'float'> 2.345
             - <type 'str'> "world !"
             - <type 'instance'> :
                 i0 <type 'int'> 100
                 s0 <type 'str'> "hello100"
                 l0 <type 'list'> :
                     - <type 'int'> 101
                     - <type 'float'> 102.0
                     - <type 'str'> "103"
                 d0 <type 'float'> 33.3333333333

  15. #15
    Membre émérite
    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
    Par défaut
    quadn je fais la même chose avec des new-style class, j'obtiens quelquechose de différent, voir étrange... :
    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
    >>> class Dummy(object):
    	def uno(self):pass
     
     
    >>> Dummy().__dict__
    {}
    >>> Dummy.__dict__
    <dictproxy object at 0x011B7F90>
    >>> Dummy.__dict__.keys()
    ['__dict__', '__module__', '__weakref__', '__doc__', 'uno']
    >>> a=Dummy()
    >>> a.__dict__
    {}
    >>> a.__dict__.keys()
    []
    >>> dir(a)
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'uno']
    >>> def dirFiltered(obj):
    	for x in dir(obj):
    		if not('__'==x[:2] and '__'==x[-2:]):
    			yield x
    >>> list(dirFiltered(a))
    ['uno']
    EDIT : Enfin, étrange... non, puisqu'en fait la méthode uno appartient à l'objet class Dummy, pas à son instance, qui fera la recherche chez ses parents, si on lui demande cette methode... C'est peut-être pour ça que les old-style class sont plus rapides...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Quote et double quote
    Par aktos dans le forum Langage
    Réponses: 8
    Dernier message: 05/01/2007, 19h55

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