105 votes

Puis-je ajouter des méthodes/attributs personnalisés aux types Python intégrés?

Par exemple—disons que je veux ajouter une méthode helloWorld() au type dict de Python. Puis-je le faire?

JavaScript a un objet prototype qui se comporte de cette manière. Peut-être que c'est une mauvaise conception et je devrais sous-classer l'objet dict, mais alors cela ne fonctionne que sur les sous-classes et je veux que cela fonctionne sur tous les futurs dictionnaires.

Voici comment cela se passerait en JavaScript:

String.prototype.hello = function() {
    alert("Bonjour, " + this + "!");
}
"Jed".hello() //alerte "Bonjour, Jed!"

Voici un lien utile avec plus d'exemples— http://www.javascriptkit.com/javatutors/proto3.shtml

106voto

TryPyPy Points 3317

Vous ne pouvez pas ajouter directement la méthode au type d'origine. Cependant, vous pouvez sous-classer le type puis le substituer dans l'espace de noms intégré/global, ce qui permet d'obtenir la plupart de l'effet souhaité. Malheureusement, les objets créés par syntaxe littérale resteront du type vanilla et n'auront pas vos nouvelles méthodes/attributs.

Voici à quoi cela ressemble

# Espace de noms intégré
import __builtin__

# Sous-classe étendue
class mystr(str):
    def first_last(self):
        if self:
            return self[0] + self[-1]
        else:
            return ''

# Substituer la str d'origine par la sous-classe dans l'espace de noms intégré
__builtin__.str = mystr

print str(1234).first_last()
print str(0).first_last()
print str('').first_last()
print '0'.first_last()

output = """
14
00

Traceback (most recent call last):
  File "strp.py", line 16, in 
    print '0'.first_last()
AttributeError: 'str' object has no attribute 'first_last'
"""

10voto

dameng Points 63

Vient d'essayer le fruit défendu!

voici le code, très simple!

from forbiddenfruit import curse

def list_size(self):
    return len(self)

def string_hello(self):
    print("Bonjour, {}".format(self))

if __name__ == "__main__":
    curse(list, "size", list_size)
    a = [1, 2, 3]
    print(a.size())
    curse(str, "hello", string_hello)
    "Jesse".hello()

9voto

fr_andres Points 1420

REMARQUE: ce QA est marqué comme étant un doublon de celui-ci, mais à mon avis, il demande quelque chose de différent. Je ne peux pas répondre là-bas, c'est pourquoi je réponds ici.


Plus précisément, je voulais hériter de str et ajouter des attributs personnalisés. Les réponses existantes (en particulier celles disant que vous ne pouvez pas) n'ont pas tout à fait résolu le problème, mais cela a fonctionné pour moi :

class TaggedString(str):
    """
    Un ``str`` avec un jeu de balises ``.tags`` et un dictionnaire ``.kwtags`` de balises.
    Exemple d'utilisation:
      ts = TaggedString("bonjour le monde!", "salutation", "cliché",
                        ce_que_je_suis="h4cker")
      (ts.upper(), ts.tags, ts.kwtags)
    """

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, args[0])

    def __init__(self, s, *tags, **kwtags):
        super().__init__()
        self.tags = set(tags)
        self.kwtags = kwtags

En espérant que cela aide quelqu'un ! Cordialement,
Andres

9voto

ax39T-Venom Points 22

Oui en effet, mais vous devez définir une nouvelle classe du même type et elle devrait hériter de ce type.

Par exemple:

class liste(liste):
    def __init__(self, *args):
        super().__init__(args)
    def map(self, fonction):
        return [fonction(i) for i in self]

a = liste(1, 2, 3, 4, 5)

def double(i):
    return i * 2

print(a.map(double))

3voto

Oui, nous pouvons ajouter des méthodes et des attributs personnalisés aux types Python intégrés. Par exemple, disons que vous voulez définir une nouvelle méthode à l'intérieur de la classe list.

Pensons à définir une classe 'list' et écrire votre propre fonction comme suit :

class list:
    def custom_method (self):
       return("Hey, je suis une méthode personnalisée de la classe list")
# créons un objet ici
obj = list([1,2,3])

print(obj.custom_method())
# Le code ci-dessus s'exécute bien, mais une liste a également une méthode append(), n'est-ce pas ?? essayons

print(obj.append(1))
"""Vous obtiendrez maintenant une erreur d'attribut : l'objet list n'a pas d'attribut append()"""

Parce que, lorsque vous définissez une classe ayant 'list' comme nom de classe, vous ne pourrez plus accéder aux méthodes de la classe 'list' intégrée car 'list' est traitée comme une classe définie par l'utilisateur plutôt qu'une classe intégrée.

Donc, pour se débarrasser de cette erreur, vous pouvez hériter des propriétés / membres de la classe 'list' et vous pouvez définir vos propres méthodes ou attributs. Ainsi, de cette manière, vous pouvez appeler des méthodes de classe définies par l'utilisateur / intégrées en utilisant le même nom de classe.

Voici à quoi cela ressemble :

# Étendre la classe list intégrée
class list(list):
     def custom_method (self):
         return("Hey, je suis une méthode personnalisée de la classe list")
obj = list([1,2,3])
print(obj.custom_method())
obj.append(1)
print(obj)

Ça fonctionne bien, et renvoie une liste modifiée [1,2,3,1].

REMARQUE : Mais lorsque vous faites cela, cela peut créer des problèmes d'ambiguïté à long terme comme des conflits de nommage

Par exemple, si vous aviez une méthode ayant la même signature qu'une fonction intégrée dans une classe définie par l'utilisateur (disons 'list' ici), alors elle sera remplacée sans votre connaissance ou avis, vous pourrez donc ne pas utiliser sa fonctionnalité d'origine à l'avenir. En considérant le code ci-dessus, si vous définissez jamais une méthode comme append(self, valeur), la fonctionnalité originale de append() sera perdue.

Il est donc préférable d'utiliser un nom de classe différent pour le nom de votre classe plutôt que le même nom que le nom de classe intégré

Par exemple, vous pouvez déclarer une classe comme suit qui ne générera aucune erreur ou vous ne rencontrerez aucun conflit de nommage.

class custom_list(list):
     def custom_method (self):
         return("Hey, je suis une méthode personnalisée de la classe list")
obj = custom_list([1,2,3])
print(obj.custom_method())
obj.append(1)
print(obj)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X