2017-07-05 2 views
-1

Est-il possible de sous-classe int et le rendre mutable?Comment sous-classer int et le rendre mutable

Tenir compte de la classe suivante:

class CustomBitVector(int): 

    # bit 7 
    @property 
    def seventh_property(self): 
     return bool(self & (1 << 7)) 

    @seventh_property.setter 
    def seventh_property(self, val): 
     self |= bool(val) << 7 

    # bit 6 
    @property 
    def sixth_property(self): 
     return bool(self & (1 << 6)) 

    @sixth_property.setter 
    def sixth_property(self, val): 
     self |= bool(val) << 6 


    # ... a few more of these ... 

    # bit 0 
    @property 
    def zeroth_property(self): 
     return bool(self & (1 << 0)) 

    @zeroth_property.setter 
    def zeroth_property(self, val): 
     self |= bool(val) << 0 

J'essaie de faire une interface agréable à un vecteur de bits. Je suis en train de lire un protocole propriétaire d'une socket et j'ai fait des classes pour représenter les messages que j'envoie/reçois. Souvent, ces messages incluent des vecteurs binaires et il serait bon de les traiter comme ça.

Cela fonctionne déjà très bien pour lire les valeurs de vecteur binaire, mais les définir ne fonctionne pas car int est immuable.

Si je réécris un des compositeurs comme:

@sixth_property.setter 
def sixth_property(self, val): 
    print 'before:', self 
    self |= bool(val) << 6 
    print 'after:', self 

Puis-je obtenir ce comportement:

In [2]: c = CustomBitVector() 

In [3]: c.sixth_property 
Out[3]: False 

In [4]: c.sixth_property = True 
before: 0 
after: 64 

In [5]: c 
Out[5]: 0 

In [6]: c.sixth_property 
Out[6]: False 

Je peux voir ma folie ... J'assignant à self au lieu de modifier il. Comment puis-je modifier self dans ce cas?

Tout piratage fou pour y arriver? Peut-être utiliser une métaclasse ou quelque chose?


MISE À JOUR

j'oublié de mentionner une exigence:

Les instances de CustomBitVector doivent se comporter comme int. En particulier, je dois être en mesure de les passer à struct.pack

+0

Vous ne pouvez pas rendre l'entier lui-même modifiable (sauf si vous écrivez une extension en C), mais vous pouvez certainement l'utiliser au lieu de l'étendre. –

Répondre

3

Est-il possible de sous-classe int et le rendre mutable?

Trier par. Vous pouvez ajouter toutes les parties modifiables que vous voulez, mais vous ne pouvez pas toucher les parties int, donc le degré de mutabilité que vous pouvez ajouter ne vous aidera pas.

Au lieu de cela, n'utilisez pas une sous-classe int. Utilisez un objet régulier qui stocke un int. Si vous voulez être en mesure de passer à struct.pack comme un int, mettre en œuvre une méthode __index__ pour définir la façon d'interpréter votre objet comme int:

class IntLike(object): # not IntLike(int): 
    def __init__(self, value=0): 
     self.value = value 
    def __index__(self): 
     return self.value 
    ... 

Vous pouvez mettre en œuvre des méthodes supplémentaires comme __or__ pour | et __ior__ pour en -place, mutatif |=. N'essayez pas de pousser trop fort pour une interopérabilité complète avec les ints, cependant; par exemple, n'essayez pas de rendre vos objets utilisables en tant que clés dict. Ils sont mutables, après tout.

S'il est vraiment important pour vous que votre classe soit une sous-classe int, vous devrez sacrifier la syntaxe c.sixth_property = True que vous voulez. Vous devrez choisir une alternative comme c = c.with_sixth_property(True), et implémenter les choses de manière non-mutative.

+0

fonctionne comme un champion, et oui, le plus important est qu'il peut être utilisé avec 'struct.pack'. – Stephen