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 :

Problème de compréhension au sujet des classes/instances de classes


Sujet :

Python

  1. #1
    Membre éprouvé Avatar de LeNarvalo
    Homme Profil pro
    Amateur Python
    Inscrit en
    février 2014
    Messages
    547
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Amateur Python
    Secteur : Santé

    Informations forums :
    Inscription : février 2014
    Messages : 547
    Points : 910
    Points
    910
    Par défaut Problème de compréhension au sujet des classes/instances de classes
    Bonjoir !

    Après 5 ans confronté à ce "problème" je me suis dit qu'il était temps de comprendre pourquoi je dois procéder ainsi avec le module Pynput (doc). Quelqu'un pourrait-il m'expliquer pourquoi je dois passer par str(key) pour que ça marche ? Comment il fait le print pour afficher 'a' si c'est une instance de classe ? Je sens qu'il me manque des connaissances basiques...

    (PS : En réalité j'utilise dans mes conditions key.vk ou key.char mais je suis obligé de passer par des try except car key n'a pas toujours l'attribut voulu)

    Un bout de mon script :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def on_release(key):
        print(key)
        print(type(key))
        print(dir(key))
        if key == "'a'":
            print("toto")
        if str(key) == "'a'":
            print("titi")
     
    with keyboard.Listener(
            on_release=on_release) as listener:
        listener.join()
    Résultat quand je presse la touche A de mon clavier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    'a'
    <class 'pynput.keyboard._win32.KeyCode'>
    ['_PLATFORM_EXTENSIONS', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_flags', '_from_ext', '_parameters', '_scan', 'char', 'combining', 'from_char', 'from_dead', 'from_vk', 'is_dead', 'join', 'vk']
    titi
    Pour ceux qui auraient besoin de voir le module _win32 de Pynput :
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    # coding=utf-8
    # pynput
    # Copyright (C) 2015-2019 Moses Palmér
    #
    # This program is free software: you can redistribute it and/or modify it under
    # the terms of the GNU Lesser General Public License as published by the Free
    # Software Foundation, either version 3 of the License, or (at your option) any
    # later version.
    #
    # This program is distributed in the hope that it will be useful, but WITHOUT
    # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    # details.
    #
    # You should have received a copy of the GNU Lesser General Public License
    # along with this program. If not, see <http://www.gnu.org/licenses/>.
    """
    The keyboard implementation for *Windows*.
    """
     
    # pylint: disable=C0111
    # The documentation is extracted from the base classes
     
    # pylint: disable=R0903
    # We implement stubs
     
    import contextlib
    import ctypes
    import enum
    import six
     
    from ctypes import wintypes
     
    import pynput._util.win32_vks as VK
     
    from pynput._util import AbstractListener
    from pynput._util.win32 import (
        INPUT,
        INPUT_union,
        KEYBDINPUT,
        KeyTranslator,
        ListenerMixin,
        SendInput,
        SystemHook,
        VkKeyScan)
    from . import _base
     
     
    class KeyCode(_base.KeyCode):
        _PLATFORM_EXTENSIONS = (
            # Any extra flags.
            '_flags',
     
            #: The scan code.
            '_scan',
        )
     
        # Be explicit about fields
        _flags = None
        _scan = None
     
        def _parameters(self, is_press):
            """The parameters to pass to ``SendInput`` to generate this key.
     
            :param bool is_press: Whether to generate a press event.
     
            :return: all arguments to pass to ``SendInput`` for this key
     
            :rtype: dict
            """
            if self.vk:
                vk = self.vk
                scan = self._scan or 0
                flags = 0
            else:
                res = VkKeyScan(self.char)
                if (res >> 8) & 0xFF == 0:
                    vk = res & 0xFF
                    scan = self._scan or 0
                    flags = 0
                else:
                    vk = 0
                    scan = ord(self.char)
                    flags = KEYBDINPUT.UNICODE
            state_flags = (KEYBDINPUT.KEYUP if not is_press else 0)
            return dict(
                dwFlags=(self._flags or 0) | flags | state_flags,
                wVk=vk,
                wScan=scan)
     
        @classmethod
        def _from_ext(cls, vk, **kwargs):
            """Creates an extended key code.
     
            :param vk: The virtual key code.
     
            :param kwargs: Any other parameters to pass.
     
            :return: a key code
            """
            return cls.from_vk(vk, _flags=KEYBDINPUT.EXTENDEDKEY, **kwargs)
     
     
    # pylint: disable=W0212
    class Key(enum.Enum):
        alt = KeyCode.from_vk(VK.MENU)
        alt_l = KeyCode.from_vk(VK.LMENU)
        alt_r = KeyCode._from_ext(VK.RMENU)
        alt_gr = KeyCode.from_vk(VK.RMENU)
        backspace = KeyCode.from_vk(VK.BACK)
        caps_lock = KeyCode.from_vk(VK.CAPITAL)
        cmd = KeyCode.from_vk(VK.LWIN)
        cmd_l = KeyCode.from_vk(VK.LWIN)
        cmd_r = KeyCode.from_vk(VK.RWIN)
        ctrl = KeyCode.from_vk(VK.CONTROL)
        ctrl_l = KeyCode.from_vk(VK.LCONTROL)
        ctrl_r = KeyCode._from_ext(VK.RCONTROL)
        delete = KeyCode._from_ext(VK.DELETE)
        down = KeyCode._from_ext(VK.DOWN)
        end = KeyCode._from_ext(VK.END)
        enter = KeyCode.from_vk(VK.RETURN)
        esc = KeyCode.from_vk(VK.ESCAPE)
        f1 = KeyCode.from_vk(VK.F1)
        f2 = KeyCode.from_vk(VK.F2)
        f3 = KeyCode.from_vk(VK.F3)
        f4 = KeyCode.from_vk(VK.F4)
        f5 = KeyCode.from_vk(VK.F5)
        f6 = KeyCode.from_vk(VK.F6)
        f7 = KeyCode.from_vk(VK.F7)
        f8 = KeyCode.from_vk(VK.F8)
        f9 = KeyCode.from_vk(VK.F9)
        f10 = KeyCode.from_vk(VK.F10)
        f11 = KeyCode.from_vk(VK.F11)
        f12 = KeyCode.from_vk(VK.F12)
        f13 = KeyCode.from_vk(VK.F13)
        f14 = KeyCode.from_vk(VK.F14)
        f15 = KeyCode.from_vk(VK.F15)
        f16 = KeyCode.from_vk(VK.F16)
        f17 = KeyCode.from_vk(VK.F17)
        f18 = KeyCode.from_vk(VK.F18)
        f19 = KeyCode.from_vk(VK.F19)
        f20 = KeyCode.from_vk(VK.F20)
        home = KeyCode._from_ext(VK.HOME)
        left = KeyCode._from_ext(VK.LEFT)
        page_down = KeyCode._from_ext(VK.NEXT)
        page_up = KeyCode._from_ext(VK.PRIOR)
        right = KeyCode._from_ext(VK.RIGHT)
        shift = KeyCode.from_vk(VK.LSHIFT)
        shift_l = KeyCode.from_vk(VK.LSHIFT)
        shift_r = KeyCode.from_vk(VK.RSHIFT)
        space = KeyCode.from_vk(VK.SPACE, char=' ')
        tab = KeyCode.from_vk(VK.TAB)
        up = KeyCode._from_ext(VK.UP)
     
        media_play_pause = KeyCode._from_ext(VK.MEDIA_PLAY_PAUSE)
        media_volume_mute = KeyCode._from_ext(VK.VOLUME_MUTE)
        media_volume_down = KeyCode._from_ext(VK.VOLUME_DOWN)
        media_volume_up = KeyCode._from_ext(VK.VOLUME_UP)
        media_previous = KeyCode._from_ext(VK.MEDIA_PREV_TRACK)
        media_next = KeyCode._from_ext(VK.MEDIA_NEXT_TRACK)
     
        insert = KeyCode._from_ext(VK.INSERT)
        menu = KeyCode.from_vk(VK.APPS)
        num_lock = KeyCode._from_ext(VK.NUMLOCK)
        pause = KeyCode.from_vk(VK.PAUSE)
        print_screen = KeyCode._from_ext(VK.SNAPSHOT)
        scroll_lock = KeyCode.from_vk(VK.SCROLL)
    # pylint: enable=W0212
     
     
    class Controller(_base.Controller):
        _KeyCode = KeyCode
        _Key = Key
     
        def __init__(self, *args, **kwargs):
            super(Controller, self).__init__(*args, **kwargs)
     
        def _handle(self, key, is_press):
            SendInput(
                1,
                ctypes.byref(INPUT(
                    type=INPUT.KEYBOARD,
                    value=INPUT_union(
                        ki=KEYBDINPUT(**key._parameters(is_press))))),
                ctypes.sizeof(INPUT))
     
     
    class Listener(ListenerMixin, _base.Listener):
        #: The Windows hook ID for low level keyboard events, ``WH_KEYBOARD_LL``
        _EVENTS = 13
     
        _WM_INPUTLANGCHANGE = 0x0051
        _WM_KEYDOWN = 0x0100
        _WM_KEYUP = 0x0101
        _WM_SYSKEYDOWN = 0x0104
        _WM_SYSKEYUP = 0x0105
     
        # A bit flag attached to messages indicating that the payload is an actual
        # UTF-16 character code
        _UTF16_FLAG = 0x1000
     
        # A special virtual key code designating unicode characters
        _VK_PACKET = 0xE7
     
        #: The messages that correspond to a key press
        _PRESS_MESSAGES = (_WM_KEYDOWN, _WM_SYSKEYDOWN)
     
        #: The messages that correspond to a key release
        _RELEASE_MESSAGES = (_WM_KEYUP, _WM_SYSKEYUP)
     
        #: Additional window messages to propagate to the subclass handler.
        _WM_NOTIFICATIONS = (
            _WM_INPUTLANGCHANGE,
        )
     
        #: A mapping from keysym to special key
        _SPECIAL_KEYS = {
            key.value.vk: key
            for key in Key}
     
        _HANDLED_EXCEPTIONS = (
            SystemHook.SuppressException,)
     
        class _KBDLLHOOKSTRUCT(ctypes.Structure):
            """Contains information about a mouse event passed to a
            ``WH_KEYBOARD_LL`` hook procedure, ``LowLevelKeyboardProc``.
            """
            _fields_ = [
                ('vkCode', wintypes.DWORD),
                ('scanCode', wintypes.DWORD),
                ('flags', wintypes.DWORD),
                ('time', wintypes.DWORD),
                ('dwExtraInfo', ctypes.c_void_p)]
     
        #: A pointer to a :class:`KBDLLHOOKSTRUCT`
        _LPKBDLLHOOKSTRUCT = ctypes.POINTER(_KBDLLHOOKSTRUCT)
     
        def __init__(self, *args, **kwargs):
            super(Listener, self).__init__(*args, **kwargs)
            self._translator = KeyTranslator()
            self._event_filter = self._options.get(
                'event_filter',
                lambda msg, data: True)
     
        def _convert(self, code, msg, lpdata):
            if code != SystemHook.HC_ACTION:
                return
     
            data = ctypes.cast(lpdata, self._LPKBDLLHOOKSTRUCT).contents
            is_packet = data.vkCode == self._VK_PACKET
     
            # Suppress further propagation of the event if it is filtered
            if self._event_filter(msg, data) is False:
                return None
            elif is_packet:
                return (msg | self._UTF16_FLAG, data.scanCode)
            else:
                return (msg, data.vkCode)
     
        @AbstractListener._emitter
        def _process(self, wparam, lparam):
            msg = wparam
            vk = lparam
     
            # If the key has the UTF-16 flag, we treat it as a unicode character,
            # otherwise convert the event to a KeyCode; this may fail, and in that
            # case we pass None
            is_utf16 = msg & self._UTF16_FLAG
            if is_utf16:
                msg = msg ^ self._UTF16_FLAG
                scan = vk
                key = KeyCode.from_char(six.unichr(scan))
            else:
                try:
                    key = self._event_to_key(msg, vk)
                except OSError:
                    key = None
     
            if msg in self._PRESS_MESSAGES:
                self.on_press(key)
     
            elif msg in self._RELEASE_MESSAGES:
                self.on_release(key)
     
        # pylint: disable=R0201
        @contextlib.contextmanager
        def _receive(self):
            """An empty context manager; we do not need to fake keyboard events.
            """
            yield
        # pylint: enable=R0201
     
        def _on_notification(self, code, wparam, lparam):
            """Receives ``WM_INPUTLANGCHANGE`` and updates the cached layout.
            """
            if code == self._WM_INPUTLANGCHANGE:
                self._translator.update_layout()
     
        def _event_to_key(self, msg, vk):
            """Converts an :class:`_KBDLLHOOKSTRUCT` to a :class:`KeyCode`.
     
            :param msg: The message received.
     
            :param vk: The virtual key code to convert.
     
            :return: a :class:`pynput.keyboard.KeyCode`
     
            :raises OSError: if the message and data could not be converted
            """
            # If the virtual key code corresponds to a Key value, we prefer that
            if vk in self._SPECIAL_KEYS:
                return self._SPECIAL_KEYS[vk]
            else:
                return KeyCode(**self._translate(
                    vk,
                    msg in self._PRESS_MESSAGES))
     
        def _translate(self, vk, is_press):
            """Translates a virtual key code to a parameter list passable to
            :class:`pynput.keyboard.KeyCode`.
     
            :param int vk: The virtual key code.
     
            :param bool is_press: Whether this is a press event.
     
            :return: a paramter list to the :class:`pynput.keyboard.KeyCode`
                constructor
            """
            return self._translator(vk, is_press)
     
        def canonical(self, key):
            # If the key has a scan code, and we can find the character for it,
            # return that, otherwise call the super class
            scan = getattr(key, '_scan', None)
            if scan is not None:
                char = self._translator.char_from_scan(scan)
                if char is not None:
                    return KeyCode.from_char(char)
     
            return super(Listener, self).canonical(key)


    Merci d'avance !

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    juin 2008
    Messages
    19 597
    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 : 19 597
    Points : 33 861
    Points
    33 861
    Par défaut
    Salut,

    print d'un objet affiche le retour de str appliqué à cet objet... qui appelle, si elle existe, la méthode __str__ définie pour cet objet (sinon çà utilise le "défaut").

    Ce que retourne cette méthode peut être n'importe quelle chaîne de caractères... enfin une qui ait un rapport avec l'instance et utile à l'appelant.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre émérite Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    septembre 2013
    Messages
    1 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : septembre 2013
    Messages : 1 382
    Points : 2 924
    Points
    2 924
    Par défaut
    bonjour, pas sûr de comprendre le problème "car key n'a pas toujours l'attribut voulu" et je n'ai pas de win pour tester

    Comment il fait le print pour afficher 'a' si c'est une instance de classe ?
    Avec toute classe on peut définir .__str__(), cette méthode va être utilisée dans 2 cas:
    - print(objet) / print(f"{objet}")
    - str(objet)

    Oui, c'est faux puisque ici on compare un objet "KeyCode" avec une chaine
    $moi= ( !== ) ? : ;

  4. #4
    Membre éprouvé Avatar de LeNarvalo
    Homme Profil pro
    Amateur Python
    Inscrit en
    février 2014
    Messages
    547
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Amateur Python
    Secteur : Santé

    Informations forums :
    Inscription : février 2014
    Messages : 547
    Points : 910
    Points
    910
    Par défaut
    Ok !

    Merci à vous deux, je comprends maintenant, j'ai en effet trouvé une méthode __str__ dans un autre module _base.py. Je cherchais désespérément une sorte de return, j'ai finalement découvert l'existence des repr() dans la métode __str__. (C'est pas bizarre d'ailleurs ? Sachant qu'il a aussi une méthode __repr__)

    Citation Envoyé par papajoker 🃏
    pas sûr de comprendre le problème "car key n'a pas toujours l'attribut voulu" et je n'ai pas de win pour tester
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    def on_release(key):
        print(key)
        print(key.char)
        print(key.vk)
        print('____________________')
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    'a'
    a
    65
    ____________________
    Key.enter
    Unhandled exception in listener callback
    Traceback (most recent call last):
        line 127, in on_release
        print(key.char)
    AttributeError: 'Key' object has no attribute 'char'
    Après ce n'est pas très problématique...

  5. #5
    Membre émérite Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    septembre 2013
    Messages
    1 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : septembre 2013
    Messages : 1 382
    Points : 2 924
    Points
    2 924
    Par défaut
    .__repr__() est pour une représentation pour développeur ClientShort{name:str255="Dupond", "city":str45="Paris"} c'est un format qui devrait être capable de reconstruire l'objet depuis cette chaine.
    .__str()__() représentation pour utilisateur name: "Dupond", city: "Paris" format totalement libre (on peut même masquer des attributs).
    repr() ne fait que appeler la méthode .__repr__()

    Très souvent __str__ est écrit par les développeurs (donc les dev poo connaissent bien), rarement __repr__ (mais un simple return str(self.__dict__) fait l'affaire)

    Avoir un def __str__(self): return repr(self) n'a pas de sens car, si str() ne trouve pas __str__ , il va appeler __repr__

    -------

    Pour ton erreur, je supose qu'une touche "muette" n'a pas d'attribut "charactère". Choix de conception au lieux de faire un "key.char == None"
    $moi= ( !== ) ? : ;

  6. #6
    Membre éprouvé Avatar de LeNarvalo
    Homme Profil pro
    Amateur Python
    Inscrit en
    février 2014
    Messages
    547
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Amateur Python
    Secteur : Santé

    Informations forums :
    Inscription : février 2014
    Messages : 547
    Points : 910
    Points
    910
    Par défaut
    Okay, trugarez (merci) !

    Quelques petites questions pour finir :

    ClientShort{name:str255="Dupond", "city":str45="Paris"}
    J'obtiens comment ce truc ? Il manque pas des guillemets autour de "name" en plus ?


    Citation Envoyé par papjoker
    Avoir un def __str__(self): return repr(self) n'a pas de sens car, si str() ne trouve pas __str__ , il va appeler __repr__
    Et en voyant ça ↓ , ça aurait plus de sens ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        def __repr__(self):
            if self.is_dead:
                return '[%s]' % repr(self.char)
            if self.char is not None:
                return repr(self.char)
            else:
                return '<%d>' % self.vk
     
        def __str__(self):
            return repr(self)
    Ah sinon pynput marche avec Linux & Co normalement.

  7. #7
    Membre émérite Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    septembre 2013
    Messages
    1 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : septembre 2013
    Messages : 1 382
    Points : 2 924
    Points
    2 924
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    Et en voyant ça ↓ , ça aurait plus de sens ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        def __str__(self):
            return repr(self)
    Justement non
    str() cherche si la méthode __str__() existe, si elle n'existe pas, utilise __repr__() qui elle existe toujours (via le parent objet)
    Donc, créer __str__() et que ce __str__() appelle uniquement __repr__(), c'est du code pour rien
    ps: voir code plus bas, tu peux renommer __str__() en x__str__() pour voir le résultat


    J'obtiens comment ce truc ? Il manque pas des guillemets autour de "name" en plus ?
    __repr__() c'est uniquement pour le developpeur, pour du debug, donc le développeur peut écrire tout ce qui lui semble pertinant
    Ici, j'ai grandement exagéré en incluant un type et une longeur (donc un modèle lié à une table ?). la longueur n'a pas forcément de sens , mais le type de chaque attribut, pourquoi pas...
    Normalement (99%), c'est une représentation classique type Json

    Citation Envoyé par papajoker
    Très souvent __str__ est écrit par les développeurs (donc les dev poo connaissent bien), rarement __repr__
    En fait tout dépend de l'objet (système/métier) et si programmation MVC ou non, pour un objet système comme KEY qui n'est pas voué à être affiché seul __repr__() est requis (requis si nous faisons des print() pour debug au lieux d'utiliser un debugger!). Pour un objet métier CLIENT, sans mvc, c'est __str__() qui va être le plus utilisé

    code exemple (on peut renommer __str__ puis __repr__ pour faire mumuse et voir le résultat sans l'un ou l'autre)
    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
    from datetime import date
     
    class Point:
        def __init__(self):
            self.x = 99
            self.y = 8
        def __str__(self):
            return f"{self.x:04}x{self.y:04}"
        def __repr__(self):
            return f'{self.__class__.__name__}{{x: {self.x}, y: {self.y}}} \tpar défaut c\'était: {object.__repr__(self)}'
     
    class Test:
        def __init__(self):
            self.name = "Durant"
            self.age = 8
            self._sexe = None
        def __str__(self):
            return f"Nom: {self.name}, Naissance: {date.today().year-self.age}\t{'#'*self.age}"   # ou affiche un seul réel attribut
        def __repr__(self):
            return f'{self.__class__.__name__}{{name:"{self.name}", age: {self.age}, _sexe:{self._sexe}}} \tpar défaut c\'était: {object.__repr__(self)}'
     
    a = Test()
    print(a)
    print(repr(a))
    print(f"{a=}")
    print()
     
    b = Point()
    print(b)
    print(repr(b))
    print(f"{b=}")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Nom: Durant, Naissance: 2014    ########
    Test{name:"Durant", age: 8, _sexe:None}         par défaut c'était: <__main__.Test object at 0x7f7952fbc190>
    a=Test{name:"Durant", age: 8, _sexe:None}       par défaut c'était: <__main__.Test object at 0x7f7952fbc190>
     
    0099x0008
    Point{x: 99, y: 8}      par défaut c'était: <__main__.Point object at 0x7f79532d7bb0>
    b=Point{x: 99, y: 8}    par défaut c'était: <__main__.Point object at 0x7f79532d7bb0>
    La différence entre les 2 est ici très claire ! et les 2 sont ici pour remplacer le "__main__.Point object at 0x7f79532d7bb0" mais dans un contexte différent

    __repr__ : uniquement pour du debug (manuel à base de print)
    __str__, si présent, affichage formaté pour utilisateur, ou formaté pour être plus simple à lire pour le dev (peut-être parfois suffisant pour du debug, commme Point ici)

    EDIT: pour le __repr__() de "ta" classe "key", en fait je trouve qu'elle est fausse (donc bon exemple ) puisque ne représente qu'une partie formatée (voir tronquée) du réel objet. Pour moi, c'est un code qui devrait être plutot dans __str__(). Et avoir dans __repr__() un code qui retourne toujours 3 valeurs (is_dead,char,keycode). Cela éviterait aux developpeurs de faire ton print(key) print(key.char) print(key.vk) en mode debug

    RE-EDIT : trouvé le code source de la classe KeyCode
    Existe .__eq__(self, other), le codeur aurait pu faire un test si "other" est str (ou int), il traite justement ces 2 cas à la ligne suivante. Cela aurait permit d'écrire directement if key == 'a': ou if key == 158:.
    A la vue des sources, le plus simple actuellement, pour ton test "if", tu peux faire un if key == KeyCode(char="a") :
    $moi= ( !== ) ? : ;

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

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Alimentation

    Informations forums :
    Inscription : juillet 2006
    Messages : 3 225
    Points : 5 894
    Points
    5 894
    Par défaut
    Bonjour,

    Souvent on utilise cette notation,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def __str__(self):
        return ...
     
    __repr__ = __str__
    Mais si on utilise comme j'ai pu voir repr(self), alors oui mieux vaut que la méhode __repr__ est été définie dans cette même classe à mon sens, si on veut suivre une certaine logique.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

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

Discussions similaires

  1. Réponses: 21
    Dernier message: 30/09/2018, 15h39
  2. Réponses: 1
    Dernier message: 07/10/2010, 17h22
  3. Petite précision au sujet des classes
    Par gmailex dans le forum Windows Forms
    Réponses: 4
    Dernier message: 19/10/2007, 23h42
  4. [JAXB][XSD] Problème lors de la génération des classes
    Par charlot44 dans le forum Persistance des données
    Réponses: 4
    Dernier message: 22/06/2005, 16h10
  5. Problème de compréhension des ensembles
    Par Cornell dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 22h07

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