2016-05-28 9 views
3

В Python 3 все должно быть объектом, даже номерами, но они неизменяемым.Можно ли сделать объект-обертку для чисел, например. плавать, чтобы сделать его изменчивым?

Можно ли создать объект-обертку для чисел, например. float, так что он будет вести себя как обычные числа, кроме того, что он должен быть изменен?

Я задавался вопросом, будет ли это возможно с помощью встроенного типа функции путем создания анонимной объект-оболочку, производный от поплавка, но изменить его поведение, чтобы быть изменяемым.

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

Какие параметры я должен изменить ф сделать номер в быть изменяемым?

Как проверить, является ли число изменчиво:

я должен быть в состоянии создать такую ​​функцию е что бы создать из целого значения значение с плавающей точкой и после поверхностного копирования он будет вести себя следующим образом:

>>> 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] 

Изменение первого списка, изменивших их оба.

Возможно, я должен добавить несколько полей в dict() или добавить дополнительный базовый класс, который обеспечил бы изменчивость?

ответ

3

Ценности неизменяемы. Это платонические формы. Выражение вроде 5 := 3 бессмысленно. Изменчивыми являются locations, обычно называемые адресами или указателями. У Python нет таких, но мы можем подделать его, используя тип контейнера, такой как list, который действительно является местоположением, которое ссылается на другие местоположения.

Ниже приведена частичная реализация изменяемого числового типа с использованием list для хранения местоположения, в котором мы будем хранить значение числа и изменять значение в этом месте, когда оно должно измениться, и потому что все копии изменяемого номера разделит это место, все копии будут видеть изменения

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 

Пожалуйста, дайте мне знать, если что-то неясно, и я могу добавить больше документации