2010-12-15 1 views
2

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

Я просто интересно, что будет лучшим способом сказать погоды строка форматируется так:

номер блока Блок

пример: 30 см дюйм (это было бы запустить функция называется cmtoinch, проходящей число 30 в качестве аргумента).

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

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

+0

Чтобы узнать, содержит ли список элемент, вы можете использовать 'in'. Итак, (строка 1) 'L = [1, 3, 5]' (строка 2) 'if 1 в L: # do whatever'. –

ответ

4

Использование .split() на строку, чтобы разбить его на слова (то вы можете повторно интерпретировать первый диск как int или float в зависимости от обстоятельств). Полученный список будет в том же порядке, что и входная строка, поэтому вы можете поочередно просматривать каждый элемент и проверять его на соответствие списку ссылок.

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

Чтобы установить связь между наименованиями единиц и значениями преобразования, мы используем dict. Это позволяет нам напрямую посмотреть значение преобразования, подключив его.

conversion_rates = { 
    'in': 2.54, # 2.54 inches in a centimetre 
    'cm': 1.00, # this is our reference unit 
    'sun': 3.03 # a traditional Japanese unit of measurement 
} 

# raises ValueError if the number of words in the input is wrong 
amount, original_unit, final_unit = line.split() 

# raises ValueError if the amount is not formatted as a floating-point number 
amount = float(amount) 

# Now we do the conversion. 
# raises KeyError if either unit is not found in the dict. 
result = amount * conversion_rates[original_unit]/conversion_rates[final_unit] 
+0

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

3

В зависимости от организации этого кода, вы можете использовать globals(), <modulename>.__dict__ или getattr(obj). В моем примере используется globals().

def cmtoinch(x): 
    return x/2.54 

def inchtocm(x): 
    return x * 2.54 

def convert(input): 
    num, unit1, unit2 = input.split() 
    func = unit1 + "to" + unit2 
    if func in globals(): 
    return globals()[func](float(num)) 
    else: 
    raise NotImplementedException() 
+1

Каждый раз, когда вы добавляете новый блок, вы удваиваете количество необходимых функций.Лучше иметь внутреннее представление (выбрать блок) и перевести с входного устройства на это, а оттуда на блок вывода - на отдельные этапы. Это означает добавление только двух функций для каждого нового устройства. Возможно, вам понадобится «тип» для блоков, чтобы предотвратить, например, перевод с галлонов на килограммы :) – sje397

+1

@ sje397 понял, но не зная точных требований к оригинальному плакату, я точно ответил на его вопрос. – robert

2

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

#!/usr/bin/python2 

import sys 

def inch2cm(inches): 
    return inches * 2.54 

def cm2inch(cm): 
    return cm/2.54 


DISPATCH_TABLE = { 
    ("in", "cm"): inch2cm, 
    ("cm", "in"): cm2inch, 
} 

def converter(argv): 
    """converter <value> <from unit> <to unit> 
    """ 
    try: 
     value = float(argv[1]) 
     unit_from = argv[2] 
     unit_to = argv[3] 
    except (ValueError, IndexError), ex: 
     print ex 
     print converter__doc__ 
     return 2 

    func = DISPATCH_TABLE[(unit_from.lower()[:2], unit_to.lower()[:2])] 
    print func(value) 

    return 0 


sys.exit(converter(sys.argv)) 

Не сказать, что это лучший способ преобразования единиц измерения, а просто демонстрация функций диспетчеризации.

Мне нравится это лучше, чем выбор из globals(), потому что он более явный и безопасный.

+0

+1 лучше, чем использование глобальных переменных() –

0

Как это?

class Translator(): 
    UNITS = [ 
     # length 
     { 
      "cm": 1.0, 
      "inch": 2.54, 
      "foot": 30.48, 
      "rod": 502.92 
     }, 
     # weight 
     { 
      "kg": 1.0, 
      "pound": 0.454, 
      "stone": 6.356 
     }, 
     # liquid volume 
     { 
      "litre": 1.0, 
      "pint": 0.473, 
      "gallon": 3.785 
     } 
    ] 

    def translate(self, val, unit1, unit2): 
     for u in Translator.UNITS: 
      if u.has_key(unit1) and u.has_key(unit2): 
       return float(val) * u[unit1]/u[unit2] 

     return "Can't convert from %s to %s" % (unit1, unit2) 

    def translateString(self, str): 
     args = str.split() 
     if len(args)==3: 
      return self.translate(float(args[0]), args[1], args[2]) 
     else: 
      return "Exactly three arguments required!" 

def main(): 
    t = Translator() 

    while True: 
     inp = raw_input("Translate what? (hit Enter to quit) ") 
     if len(inp) > 0: 
      t.translateString(inp) 
     else: 
      break