l'héritage de str ou int
Pourquoi j'ai des problèmes pour créer une classe héritant de str (ou int)
class C(str):
def __init__(self, a, b):
str.__init__(self,a)
self.b = b
C("a", "B")
TypeError: str() takes at most 1 argument (2 given)
tha même si j'essaie d'utiliser int
au lieu de str
, mais il fonctionne avec des classes personnalisées. J'ai besoin d'utiliser __new__
au lieu de __init__
? pourquoi?
Vous devez vous connecter pour publier un commentaire.
Depuis
__init__
est appelé après que l'objet est construit, il est trop tard pour modifier la valeur d'immuable types. Notez que__new__
est un classmethod, j'ai donc appelé le premier paramètrecls
Voir ici pour plus d'informations
Hériter de types intégrés est très rarement utile. Vous devez faire face à plusieurs problèmes, et vous n'avez pas vraiment beaucoup d'avantages.
Il est presque toujours préférable d'utiliser la composition. Au lieu d'hériter de
str
, vous devez garder unstr
objet comme un attribut.vous pouvez reporter les méthodes que vous souhaitez travailler sur le sous-jacent
str
self.s
manuellement ou automatiquement à l'aide de__getattr__
.Cela étant dit, qui ont besoin de votre propre type de chaîne est quelque chose qui devrait vous donner une pause. Il y a beaucoup de classes qui doit stocker une chaîne de données principale, mais en général, vous souhaitez utiliser
str
ouunicode
(le dernier si vous êtes représentant de texte) pour la représentation générale de chaînes de caractères. (Une commune exception est si vous avez besoin d'utiliser une INTERFACE toolkit de type chaîne de caractères.) Si vous voulez ajouter des fonctionnalités à vos chaînes, essayez si vous pouvez utiliser les fonctions qui opèrent sur les chaînes plutôt que de nouveaux objets pour servir en tant que chaînes, ce qui rend votre code plus simple et plus compatible avec tous les autres programmes.__getattr__
?__getattr__
de reporter sinon pas défini des attributs à un attribut spécifique dans la composition est accompli par un code commedef __getattr__(self, name): return getattr(self.s, name)
. Notez que ce code n'est pas forcément recommandé, mais peut bien fonctionner dans certains cas, il est souvent préférable de définir manuellement les choses que vous voulez dans la composition.c_function(char*)
, je peux l'utiliser en python commec_function(s)
oùs
est unstr
instance. s de représenter quelque chose, et je veux qu'il ait unename
, unbeautiful_name
et ainsi de suite. J'ai donc dérivé d'une classeC
destr
, donc je peux passer un objet c de classeC
àpython_function
que, par exemple, neprint c.name
et appelc_function(c)
str
est une source potentielle d'erreur, mais n'est pas réellement vous aider.your_subclass[:5]
ouyour_subclass.replace(x, y)
--que faut-il de retour? Une instance destr
ou une instance de votre sous-classe? Ce n'est pas encore défini, mais dans la pratique, il sera de retourstr
. Il n'y a aucune garantie de quelque manière que ce soit, et ce genre de comportement indéfini est une mauvaise chose.Lorsque vous instancier une classe, les arguments que vous passer en, sont transmis à la fois la
__new__
(constructeur), puis à la__init__
(initialiseur) les méthodes de la classe. Donc, si vous hériter d'une classe qui a des restrictions sur le nombre d'arguments qui peuvent être fournis lors de l'instanciation, vous devez vous assurer que ni ses__new__
, ni ses__init__
aurait plus d'arguments qu'ils s'attendent à obtenir. Donc, c'est le problème que vous avez. Vous instanciez votre classe avecC("a", "B")
. L'interprète cherche__new__
méthode dansC
.C
ne l'a pas, donc python jette un coup d'oeil dans sa classe de basestr
. Et comme il en a une, c'est que l'un est utilisé et fourni avec les deux arguments. Maisstr.__new__
s'attend à obtenir un seul argument (en plus de son objet de classe comme premier argument). DoncTypeError
est soulevée. C'est pourquoi vous devez élargir votre enfant en classe de même pour ce que vous faites avec__init__
. Mais gardez à l'esprit qu'il doit retourner instance de la classe et que c'est un statique méthode (qu'il est défini par@staticmethod
décorateur ou pas) qui compte si vous utilisezsuper
fonction.>>> str.__init__('abc', 'def')
. Cela ne fait rien. Cependant,>>> str.__new__(str, 'abc', 'def')
lève l'exception:TypeError: str() takes at most 1 argument (2 given)
. C'est un peu confus, parce que nous avons appeléstr.__new__(..)
avec 3 arguments, pas les 2. Est-ce à dire questr.__new__(..)
accepte un nombre quelconque d'arguments, mais alors les appelsstr(..)
? Probablement pas, parce questr(..)
va appelerstr.__new__(..)
à son tour...__init__
méthode à tous. Ni nebasestring
(str
's de la classe de base).__init__
est héritée directement deobject
et que l'on accepte un nombre quelconque d'arguments. Au contraire__new__
méthode est vraiment mis en œuvre dansstr
et il accepte au plus 1 argument à côté de la première, qui doit êtrestr
ou de ses sous-classe. Essayez des expressions comme>>> '__init__' in str.__dict__
et ainsi de suite pour__new__
,basestring
etobject
.str.__new__(str, 'abc', 'def')
et il dit que j'ai fourni 2 arguments. Je compte trois là. Pour l'exempleclass C(object):\n @staticmethod \n def m(a): pass
, si je l'appelle commeC.m(1, 2)
, il va direTypeError: m() takes exactly 1 argument (2 given)
comme prévu. Je suppose que__new__
produit un message de confusion parce que__new__
est spécial (par exemple, vous n'avez pas besoin d'ajouter de la@staticmethod
lors de la mise en œuvre).Utilisation
__new__
en cas de immuable types:d'impression retourne
hello
.Python chaînes sont immuables types. La fonction
__new__
est appelé à créer une nouvelle instance de l'objetC
. Le python__new__
fonction est essentiellement existe pour permettre à l'héritage immuable types.type(C("a", "B"))
->NoneType
NoneType
, après le second, il a donné""
. Qui n'a pas demandé de fonctionnalité? Je n'ai pas demander à un__str__
fonction et il n'est pas nécessaire, parce que la classe héritée destr
, voir gnibbler réponse. Maintenant, je ne peux pas modifier le downvote, j'ai besoin que vous modifiez votre réponse.Après avoir lu attentivement cette, voici une autre tentative de sous-classement str. Le changement d'une autre réponse est la création de l'instance de la classe correcte à l'aide de
super(TitleText, cls).__new__
. Celui-ci semble se comporter comme un str à chaque fois qu'il est utilisé, mais m'a permis de remplacer une méthode:Ceci vous permet de tranchage et de subscripting correctement. Qu'est-ce pour? Pour renommer l'application Django dans l'admin de la page d'index.
repr
est trompeur conduit à il n'était pas clair que touta
est unTitleText
,a[0]
eta[0:2]
sont str (aujourd'hui, dans les versions actuelles, comme un détail d'implémentation). Si vous avais écrit une classe sans hériter destr
vous pourriez faire beaucoup plus utile et beaucoup moins confuse et trompeuse chose.