2016-05-28 22 views
3

In Python 3 soll alles ein Objekt sein, gerade Zahlen, aber sie sind unveränderlich.Ist es möglich, Wrapper-Objekt für Zahlen, z. schweben, um es veränderbar zu machen?

Ist es möglich Wrapper-Objekt für Zahlen, z. float, so dass es sich genau wie gewöhnliche Zahlen verhalten würde, außer dass es veränderbar sein muss?

Ich habe mich gefragt, ob es möglich wäre, mit Hilfe der integrierten in Typ Funktion, indem anonymes Wrapper-Objekt aus Float abzuleiten, sondern ändert es Verhalten wandelbar zu sein.

>>> f = lambda x : type('', (float,), dict())(x) 
>>> a = f(9) 
>>> a 
9.0 

Welche Parameter muss ich f ändern machen Nummer einem wandelbar sein?

Wie ich überprüfen, ob eine Zahl wandelbar ist:

ich in der Lage sein muss, eine solche Funktion f zu erstellen, die von Integer-Wert einen Float-Wert und nach der flache Kopie erstellen würde wäre es in der folgenden Weise verhalten:

>>> list_1 = [f(i) for i in [1, 2, 3, 4]] 
>>> list_1 
[1.0, 2.0, 3.0, 4.0] 
>>> list_2 = copy.copy(list_1) 
>>> list_1[0] *= 100 
>>> list_1 
[100.0, 2.0, 3.0, 4.0] 
>>> list_2 
[100.0, 2.0, 3.0, 4.0] 

Änderung der ersten Liste, haben beide geändert.

Vielleicht muss ich einige Felder zu dict() hinzufügen oder zusätzliche Basisklasse hinzufügen, die Mutabilität erzwingen würde?

Antwort

3

Werte sind unveränderlich. Sie sind platonische Formen. Ein Ausdruck wie 5 := 3 ist unsinnig. Was änderbar ist, sind locations, üblicherweise als Adressen oder Zeiger bezeichnet. Python hat diese nicht, aber wir können es fälschen, indem wir einen Containertyp wie list verwenden, der wirklich ein Ort ist, der auf andere Orte verweist.

Hier ist eine Teilimplementierung eines veränderbaren numerischen Typs mit einem list, um einen Speicherort zu speichern, wo wir den Wert der Zahl behalten und den Wert an diesem Speicherort ändern, und wenn alle Kopien einer veränderbaren Zahl wird diese Position teilen, werden alle Kopien der Änderung sehen

import copy 

# Convenience to work with both normal and mutable numbers 
def _get_value(obj): 
    try: 
     return obj.value[0] 
    except: 
     return obj 

class mutable_number(object): 
    def __init__(self, value): 
     # Mutable storage because `list` defines a location 
     self.value = [value] 

    # Define the comparison interface 
    def __eq__(self, other): 
     return _get_value(self) == _get_value(other) 

    def __ne__(self, other): 
     return _get_value(self) != _get_value(other) 

    # Define the numerical operator interface, returning new instances 
    # of mutable_number 
    def __add__(self, other): 
     return mutable_number(self.value[0] + _get_value(other)) 

    def __mul__(self, other): 
     return mutable_number(self.value[0] * _get_value(other)) 

    # In-place operations alter the shared location 
    def __iadd__(self, other): 
     self.value[0] += _get_value(other) 
     return self 

    def __imul__(self, other): 
     self.value[0] *= _get_value(other) 
     return self 

    # Define the copy interface 
    def __copy__(self): 
     new = mutable_number(0) 
     new.value = self.value 
     return new 

    def __repr__(self): 
     return repr(self.value[0]) 

x = mutable_number(1) 
y = copy.copy(x) 
y *= 5 
print x 

list_1 = [mutable_number(i) for i in [1, 2, 3, 4]] 
list_2 = copy.copy(list_1) 
list_1[0] *= 100 
print list_1 
print list_2 

Bitte lassen Sie mich wissen, wenn etwas unklar ist, und ich kann mehr Dokumentation hinzufügen