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 :

conversion de type avec les types hints


Sujet :

Python

  1. #1
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut conversion de type avec les types hints
    Bonjour,

    alors voila j'ai comme projet de faire une lib qui permettrait en décorant une fonction de convertir les paramètres de la fonction automatiquement, voici un petite exemple illustratif :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def add(a: int, b: int) -> int:
    	return a +b
     
    @auto_convert()
    add(5, 6) # retourne 11
     
    @auto_convert()
    add("11", 2) # retourner 13
    Alors bon pour l'instant encore rien de bien concret je fais quelques tests, il semble qu'un moyen serait inspect.signature(f).parameters, un peu de regex et des eval.

    2 questions:
    - est ce que selon vous c'est une idée intéressante ou bien est-ce que les annotations de types ne doivent être utiliser qu'en tant que simples annotations ?
    - avez vous des conseils ?

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Dans l'absolu je dirais que add("11", 2) doit retourner une TypeError et rien d'autre.

    Ce n'est pas le rôle d'un inspecteur de code de corriger un bogue et encore moins silencieusement.

    Mes deux open cents.

  3. #3
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Warning dangers detected !!!

    Alors bon pour l'instant encore rien de bien concret je fais quelques tests, il semble qu'un moyen serait inspect.signature(f).parameters, un peu de regex et des eval.
    Surtout pas eval, si tu veux des entiers, alors tu détectes que l'ensemble des caractères de ta chaîne représente des entiers...

    alors voila j'ai comme projet de faire une lib qui permettrait en décorant une fonction de convertir les paramètres de la fonction automatiquement
    À quelle fin ? où se trouve le besoin ? Si derrière il n'y a pas un objectif, ou le besoin de s'en servir, l'intérêt se trouve où ?
    Je ne vois pas dans quelle utilisation on a besoin de cela, même dans une calculatrice.
    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)

  4. #4
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    En faite j'en ai un peu marre dans mes codes de faire une tonne de if not isinstance(...): raise TypeError(...), je reviendrais d'ici avec un bout de code.

  5. #5
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Je pense que ton code exemple permet d'éviter (en ce qui me concerne) à juste titre isinstance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def auto_convert(f):    
    def wrap(*args):
            values = list(map(int, args))
            return f(*values)
        return wrap
     
     
    @auto_convert
    def add(*numbers):
        return sum(numbers)
     
     
    print(add(5, 6)) # retourne 11
    print(add("11", 2)) # retourner 13
    Après ton exemple ne perçoit peut-il pas l'entièreté de ton problème, mais va falloir trouver quelque chose d'assez modulable si tu veux l'appliquer d'une manière répétée.
    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)

  6. #6
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    bonjour,

    alors voila j'ai vraiment un embryon de test, pour pour montrer le principe. Ce code doit surement être avec des failles, il ne marche pas avec *args, **kwargs, les itérables en général mais c'est vraiment pour vous montrer le principe.

    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
    import inspect
     
     
    def convert(f):
    	def wrapper(*args, **kwargs):
    		signature = inspect.signature(f)
    		params = signature.parameters
    		bind = signature.bind(*args, **kwargs)
     
    		converted_args = []
    		converted_kwargs = {}
     
    		if True:
    			converted_args = args
    			converted_kwargs = kwargs
     
    		for k, v in bind.arguments.items():
    			if params[k].annotation != inspect._empty:
    				v = eval(f"{params[k].annotation.__name__}({v})")
    				print(type(v), v)
    			else: # il n'y a pas d'annotation
    				print(type(v), v)
     
    		print()
     
    		return f(*converted_args, **converted_kwargs)
    	return wrapper
     
     
     
    @convert
    def foobar(a: int, b: int, c: int)-> int:
    	pass
     
     
    @convert
    def foobar2(a: str, b: bool, c: int)-> int:
    	pass
     
     
     
     
     
    if __name__ == "__main__":
    	foobar(5, "8", True)
    	foobar2(5, "8", True)
    Alors des cas d'utilisation pratique ça pourrais être par exemple on a un command prompt où on ne peut saisir que sous forme de chaine de caractère, après tout pourquoi pas, c'est un cas fictif, mais imaginons:

    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 datime_converter(argument):
    	date_formats = [
    		"%d/%m/%Y+%Hh%M",	# [dd]/[mm]/[aaaa]+[HH]h[MM]
    		"%d/%m/%Y+%HH%M",	# [dd]/[mm]/[aaaa]+[HH]H[MM]
    		"%d/%m/%Y+%H:%M",	# [dd]/[mm]/[aaaa]+[HH]:[MM]
    		"%d/%m/%Y",			# [dd]/[mm]/[aaaa]
    		"%d-%m-%Y+%Hh%M",	# [dd]-[mm]-[aaaHH+[HH]h[MM]
    		"%d-%m-%Y+%HH%M",	# [dd]-[mm]-[aaaHH+[HH]H[MM]
    		"%d-%m-%Y+%H:%M",	# [dd]-[mm]-[aaaa]+[HH]:[MM]
    		"%d-%m-%Y",			# [dd]-[mm]-[aaaa]
    	]
     
    	for date_format in date_formats:
    		try:
    			return dt.strptime(argument, date_format)
    		except ValueError:
    			pass
    	raise ValueError("time date {0} does not match formats {1}".format(argument, date_formats))
     
     
    def delta_d(date1: datime_converter, date2: datime_converter):
    	return date1 - date2
    bon bien sur c'est un exemple bateau, mais dans le cas d'un système de command prompt on pourra faire delta_d 11/11/2012 03/08/2015.

    J'ai eu cette idée en utilisant d.py et le système de converter, et je dois avouer que c'est pratique sauf que .. c'est propre à d.py
    Je n'ai rien inventé je me suis juste dit "est-ce que c'est possible de faire ça? est-ce que ça ne va pas pas à l'encontre même de python ?" et bien essayons, demandons

  7. #7
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Bonjour,

    Ton 1er code avec inspect ne sert à rien de plus que le code que j'ai présenté plus haut (d'ailleurs je l'ai encore raccourci) et en plus en y ajoutant une pointe de mocheté et d'horreur ligne 19.

    La ligne 14 ne sert strictement à rien... et si tu veux des paramètres nommés, alors on utilise le paramètre kwargs de ta fonction.

    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
    def convert(f):    
        def wrapper(*args, **kwargs):
            print(kwargs)
        return wrapper
     
     
     
    @convert
    def foobar(**kwargs):
        pass
     
     
    @convert
    def foobar2(**kwargs):
        pass
     
     
     
     
     
    if __name__ == "__main__":
        foobar(a=5, b=8) # {'b': 8, 'a': 5}
        foobar2(c=7, d=2) # {'c': 7, 'd': 2}
    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)

  8. #8
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    Le principe n'est pas de juste afficher *arg et **kwargs..
    Si vous aviez regardez vous auriez remarqué que le décorateur converti les paramètres grâce à ma mocheté ligne 19.
    Alors ici il est vrai que une fois converti je ne fais que afficher les arguments de la fonction, l'idée étant d'appeler la fonction avec les arguments convertis.

    Par ailleurs si à partir de <type 'unTypeQuelquonque'> vous arrivez à faire unTypeQuelconque(argument) sans eval je suis preneur.

    Ps : la ligne 14 ne sert effectivement à rien puisque pour l'instant je ne fais qu'afficher les paramètres convertis au lieu d'appeler la fonction avec les arguments convertis.
    D'ailleurs je ne met pas de if True: comme ça, ses lignes sont temporaires.

  9. #9
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Citation Envoyé par flapili Voir le message
    Le principe n'est pas de juste afficher *arg et **kwargs..
    Je le sais bien, et j'ai bien compris ce que tu tentais de faire, je t'indique juste qu'avec mon code, en affichant kwargs, tu vois comment manipuler les arguments de ta fonction pour en faire ce que tu veux

    Citation Envoyé par flapili Voir le message
    Si vous aviez regardez vous auriez remarqué que le décorateur converti les paramètres grâce à ma mocheté ligne 19.
    Alors ici il est vrai que une fois converti je ne fais que afficher les arguments de la fonction, l'idée étant d'appeler la fonction avec les arguments convertis.
    J'ai bien regardé, encore une fois, d'ailleurs ma première fonction exemple, le fait également, et cela en deux lignes.

    Citation Envoyé par flapili Voir le message
    Par ailleurs si à partir de <type 'unTypeQuelquonque'> vous arrivez à faire unTypeQuelconque(argument) sans eval je suis preneur.
    Pas compris, un exemple concret sans passer par la syntaxe python. Sans eval, facile à trouver, toujours ! Tente une explication concrète

    Citation Envoyé par flapili Voir le message
    Ps : la ligne 14 ne sert effectivement à rien puisque pour l'instant je ne fais qu'afficher les paramètres convertis au lieu d'appeler la fonction avec les arguments convertis.
    D'ailleurs je ne met pas de if True: comme ça, ses lignes sont temporaires.
    Alors ne pas mettre ces lignes, moins il y a de lignes, plus c'est simple à comprendre où tu veux en venir. Donc les lignes inutiles sont à proscrire pour se faire comprendre
    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)

  10. #10
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    Alors si je devais traduire de façon "algorithmique" :

    J'appelle la fonction avec args.
    Je crée une liste converted_args.
    Pour tout argument argdans args.
    - je regarde à quoi arg est annoté dans la définition de la fonction
    - Je converti arg en fonction de l'annotation (par exemple si j'ai int comme annotation je veux qu'il soit converti en entier, si j'ai comme annotation MaClasse alors je veux que mon argument soit converti en une instance de MaClasse.
    - J'ajoute cet argument converti à converted_args.

    puis enfin j'appelle la fonction avec converted_args

  11. #11
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    L'annotation ne sert pas à caster un type, bien au contraire, il sert à imposer un type !
    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)

  12. #12
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Salut.

    Citation Envoyé par flapili Voir le message
    Par ailleurs si à partir de <type 'unTypeQuelquonque'> vous arrivez à faire unTypeQuelconque(argument) sans eval je suis preneur.
    Sans eval, ni inspect.

    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 convert(f):
        annotations = f.__annotations__
        args_names = f.__code__.co_varnames
        def w(*args):
            c_args = []
            for i, name in enumerate(args_names):
                type_ = annotations[name]
                c_args.append(type_(args[i]))
            return f(*c_args)
        return w
     
    @convert
    def foobar(a: int, b: int, c: int)-> int:
        print(*('%s => %s' % (a, type(a)) for a in (a, b, c)))
     
    @convert
    def foobar2(a: str, b: bool, c: int)-> int:
        print(*('%s => %s' % (a, type(a)) for a in (a, b, c)))
    Mais on fait ce genre de choses pour s'amuser, pas pour l'utiliser sérieusement dans un script, je suis totalement d'accord avec VinsS et fred1599 que c'est une très mauvaise pratique.
    Le temps ronge l'amour comme l'acide.

  13. #13
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Sans savoir si ta recherche de modification de types est pertinente, je te suggère de regarder, en tant que source d'inspiration, ce que je viens de publier ici:

    https://www.developpez.net/forums/d1...de-decorateur/

    Il s'agit d'un décorateur utilisé pour vérifier les arguments d'une fonction (valeurs et types), afin d'éviter les "if... raise..." qui m'énervent aussi...

    Ce décorateur n'est pas fait pour modifier les types, mais sa structure générale le permettrait.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  14. #14
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 108
    Points
    6 108
    Par défaut
    Citation Envoyé par flapili Voir le message
    En faite j'en ai un peu marre dans mes codes de faire une tonne de if not isinstance(...): raise TypeError(...)
    Si c'est le seul motif, alors le plus simple et le plus efficace est d'utiliser un outil qui vérifie le typage statique, par exemple mypy.

    Par exemple, si je crée un fichier "test.py" avec le contenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def add(a: int, b: int) -> int:
    	return a + b
     
    add(5, 6)
     
    add("11", 2)
    et que je lance en ligne de commande mypy test.py, cela m'écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test.py:6: error: Argument 1 to "add" has incompatible type "str"; expected "int"
    Je précise que mypy n'est pas un interpréteur : il n'exécute pas le code. Il détecte l'erreur uniquement en lisant le code.

  15. #15
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Hello,

    Je ne sais pas si vous avez vu cette phrase, alors je là cite à nouveau sur ce post,

    Je converti arg en fonction de l'annotation (par exemple si j'ai int comme annotation je veux qu'il soit converti en entier, si j'ai comme annotation MaClasse alors je veux que mon argument soit converti en une instance de MaClasse
    Si je comprends bien, le PO souhaite selon les annotations, caster les paramètres de la fonction.
    Ceci est pour moi pas le travail des annotations de types.

    On est bien d'accord selon vos réponses, vous le confirmez, que les annotations imposent un type ou des types bien précis. La solution serait la création d'un décorateur.

    Cependant, à part la réponse de bistouille en partie, vous ne répondez pas à la question du PO et on est d'accord sur le fait que ce que demande le PO n'est pas une bonne pratique...

    Je verrai quand même pour ajouter une solution à la question de "convertir arg", le code ci-dessous,

    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
    import sys
     
    def deco(f):
     
        obj = {
            'int': int,
            'str': str,
        }
     
     
        def wrap(*args):
            values = []
            for ind, key in enumerate(f.__annotations__):
                fname = f.__annotations__[key].__name__
                try:
                    value = obj[fname](args[ind])
                    values.append(value)
                except ValueError:
                    print('Error with argument {}'.format(args[ind]))
                    sys.exit(-1)
            return f(*values)
        return wrap
     
     
     
     
     
     
    @deco
    def f(a: int, b: int):
        return a + b
     
     
    print(f(11, 3))
    print(f('11', 3))
    print(f('11', '3'))
    Voilà, c'est plutôt moche, moins qu'avec eval, mais c'est assez lourd... et on fait bien un cast selon les annotations présentées

    P.S J'ai pas fais tous les tests possibles (par exemple des annotations de types différentes).
    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)

  16. #16
    Membre éclairé
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 513
    Points : 700
    Points
    700
    Par défaut
    bonjour,

    Merci pour vos retours, je sais que l'annotation n'est pas pour cast, en faite je me suis dit "et pourquoi pas ? ça peux être intéressant" je n'avais jamais eu l'occasion/l'utilité de pratiquer les décorateurs et même si mon projet n'as pas vraiment de fin en soit c'est toujours intéressant.

Discussions similaires

  1. Souligner une ligne particulière avec les java hints
    Par steackfrite dans le forum Langage
    Réponses: 1
    Dernier message: 24/06/2013, 15h39
  2. Réponses: 0
    Dernier message: 04/11/2011, 10h10
  3. Réponses: 4
    Dernier message: 24/05/2007, 10h11
  4. Problème avec les champs de type table
    Par devdev dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 16/12/2004, 16h05
  5. [Débutant][Phppgadmin] problème avec les types
    Par PoY dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 19/08/2004, 17h06

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