2016-02-03 2 views
1

У меня есть два уникальных объекта температуры, которые мне нужно сравнить друг с другом, однако, поскольку объекты могут быть равны, но имеют разные единицы, я столкнулся с трудностями, сравнивая их.Переопределение __eq__ и сравнение двух объектов

Например

t1 = Temperature(32.0, 'F')

t2 = Temperature(0.0, 'C')

Эти два объекта равны, но я не могу показаться, чтобы получить правильную реализацию __eq__ сравнить их

Вот что у меня есть исп.

class Temperature(): 

    def __init__(self, temp = 0.0, unit = 'C'): 
     if float(temp) == str(temp): 
      raise ValueError('could not convert string to float: ' + "'" + str(temp) + "'") 
     else: 
      self.t = float(temp) 
     if unit.upper() not in 'CF': 
      raise UnitError('Unrecognized temperature unit ' + "'" + str(unit) + "'") 
     else: 
      self.u = unit.upper() 

    def __repr__(self): 
     return "Temperature({},'{}')".format(self.t, self.u) 

    def __str__(self): 
     return str(self.t) + '°' + self.u.upper() 

    def __eq__(self, other): 
     t1 = Temperature(self.t, self.u) 
     t2 = Temperature(other.t, other.u) 
     other.convert() 

     if t1.t == t2.t and t1.u == t2.u: 
      return True 
     return False 

    def convert(self): 
     t = Temperature(self.t, self.u) 
     if t.u.upper() == 'C': 
      t.t *= 1.8 
      t.t += 32 
      t.u = 'F' 
      return t 
     else: 
      t.t -= 32 
      t.t /= 1.8 
      t.u = 'C' 
      return t 

Обратите внимание, что у меня есть метод для преобразования температуры с одного устройства на другой. Опять же, я не могу понять, как сравнивать два объекта, когда они находятся в разных единицах.

+1

Просто нормализуется, когда вы сравните –

+0

@PadraicCunningham Я еще несколько новых для Python, вам придется расширить немного. – 23k

+0

Следите за ошибкой округления с плавающей запятой. – user2357112

ответ

0

Для сравнения температуры нет необходимости всегда конвертировать other. Вам нужно только конвертировать, когда self и other имеет разные единицы. Как только они преобразуются в одну единицу, значения температуры можно сравнить.

Также вы вернули новый объект от convert() метода. Поэтому вам нужно присвоить возвращаемое значение. И вы должны использовать абсолютное значение разницы, чтобы избежать ошибок с плавающей запятой.

Это должно работать:

def __eq__(self, other): 
    if self.u != other.u: 
     other = other.convert() 

    return math.fabs(self.t - other.t) < 1e-6 
+0

Если конверсии являются плавающей точкой, вам необходимо разрешить ошибки округления, а не требовать абсолютного равенства. – sabbahillel

+0

@sabbahillel благодарит за это. Я отредактировал свой ответ. – taskinoor

1

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

def __eq__(self, other): 
    other_temp = other.t 
    if other.u != self.u: 
     other_temp = other.convert().t 

    if self.t == other_temp: #already ensured units match 
     return True 
    return False 
1

Изменения как к одному типу и допускает ошибки с плавающей запятой:

class Temperature(): 
    def __init__(self, temp=0.0, unit='C'): 
     if float(temp) == str(temp): 
      raise ValueError('could not convert string to float: ' + "'" + str(temp) + "'") 
     else: 
      self.t = float(temp) 
     if unit.upper() not in 'CF': 
      raise Exception 
     else: 
      self.u = unit.upper() 

    def __repr__(self): 
     return "Temperature({},'{}')".format(self.t, self.u) 

    def __str__(self): 
     return str(self.t) + '°' + self.u.upper() 

    def __eq__(self, other): 
     t1, t1u = self.t, self.u 
     t2, t2u = other.t, other.u 
     other.convert() 
     self.convert() 

     equal = abs(self.t - other.t) < .0001 
     self.t, self.u = t1, t1u 
     other.t, other.u = t2, t2u 
     return equal 

    def convert(self): 
     if self.u.upper() == 'C': 
      self.t *= 1.8 
      self.t += 32 
      self.u = 'F' 

Вы не можете просто нормализовать один, как вы не знаете, что Фаренгейт или которые Цельсия, вы должны предположить, что возможны все варианты, поэтому простое изменение любого celcius to fahrenheit будет означать, что вы всегда последовательно сравниваете:

In [6]: t1 = Temperature(100, "f") 

In [7]: t2 = Temperature(37.7778, "c") 

In [8]: t1 == t2 
Out[8]: True 

In [9]: t1.t 
Out[9]: 100.0 

In [10]: t2.t 
Out[10]: 37.7778 

Вы также не хотите изменять фактический атрибут без возможности восстановления значений позже, хранения, преобразования, выполнения сравнения, а затем сброса атрибута к исходным значениям будет означать, что пользователь вернет то, что помещено.

0
  1. преобразовать в стандартный блок - скажем, конвертировать и Фаренгейта и Цельсия Кельвина или всегда преобразовывать в CENTIGRADE

  2. Ваши преобразованные значения с плавающей

  3. вы позволяете для округления ошибок, используя предельное значение

Например, Python (2.75)

import math 
lim = 1e-8 
if math.fabs(temp1 - temp2) > lim: # both have been converted 
    print 'temperatures do not match 
else: 
    print 'temperatures match' 
0

Гораздо проще хранить температуры внутри общего устройства, такого как Kelvin.

def __init__(self, temp, unit): 
    temp = float(temp) 
    # Save the original input, perhaps for display purposes 
    self.orig = temp 
    self.unit = unit 
    if unit == "K": 
     self.t = temp 
    elif unit == "C": 
     self.t = tmp + 273.15 
    elif unit == "F": 
     self.t = (temp + 459.67) * 5/9.0 
    else: 
     raise ValueError("Unrecognized unit %s" % (unit,)) 

Тогда сравнение любых двух Temperature просто вопрос о сравнении их t атрибутов.

def __eq__(self, other): 
    try: 
     return abs(self.t - other.t) < 1e-6 # Or some other tolerance 
    else AttributeError: 
     return False 
     # or raise NotImplemented