Hello World
Чтобы представить, что такое Огонь, посмотрите на простой пример, чтобы понять
# calc.py
import fire
class Calculator(object):
"""A simple calculator class."""
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Далее мы вводим bash для выполнения скрипта, написанного выше
> python calc.py double 10
20
> python calc.py double --number=16
32
Выше приведен официальный пример кода.С огнем написание программ командной строки Python становится очень простым, и нам больше не нужно иметь дело с громоздким анализом параметров командной строки. Затем мы имитируем HelloWorld и пишем сценарий командной строки для вычислений числа пи и факториала.
настоящий бой
import math
import fire
class Math(object):
def pi(self, n):
s = 0.0
for i in range(n):
s += 1.0/(i+1)/(i+1)
return math.sqrt(6*s)
def fact(self, n):
s = 1
for i in range(n):
s *= (i+1)
return s
if __name__ == '__main__':
fire.Fire(Math)
Далее мы запускаем
> python maths.py pi 10000
3.14149716395
> python maths.py pi 100000
3.14158310433
> python maths.py pi 1000000
3.14159169866
> python maths.py fact 10
3628800
> python maths.py fact 15
1307674368000
> python maths.py fact 20
2432902008176640000
Круто, это действительно удобно! fire показывает текущую структуру объекта и сопоставляет информацию о структуре с параметрами командной строки оболочки. На самом деле, у огня есть несколько режимов воздействия.Далее давайте рассмотрим режимы воздействия огня один за другим.
открытый модуль
Если огонь не передает никаких параметров, он может напрямую раскрыть текущую структуру модуля.Давайте изменим приведенный выше пример, чтобы удалить информацию о классе.
import math
import fire
def pi(n):
s = 0.0
for i in range(n):
s += 1.0/(i+1)/(i+1)
return math.sqrt(6*s)
def fact(n):
s = 1
for i in range(n):
s *= (i+1)
return s
if __name__ == '__main__':
fire.Fire()
Обратите внимание, что вызов функции Fire не имеет параметров, запустите его
> python maths.py fact 20
2432902008176640000
> python maths.py pi 1000000
3.14159169866
выставить функцию
fire также может передавать объект функции для предоставления одной функции, что позволяет нам опустить имя функции в аргументах командной строки.
import math
import fire
def pi(n):
s = 0.0
for i in range(n):
s += 1.0/(i+1)/(i+1)
return math.sqrt(6*s)
if __name__ == '__main__':
fire.Fire(pi)
Если открыта функция, может быть раскрыта только одна функция. Если открыты две функции, только последняя вступит в силу. Запустите ее.
> python maths.py 1000
3.14063805621
Выставить словарь
fire может напрямую отображать модуль, все функции текущего модуля доступны, а имя функции совпадает с именем первого параметра. Мы также можем выборочно раскрыть некоторые функции модуля, используя метод раскрытия словаря, не раскрывая все функции всего модуля, и, кстати, мы также можем заменить открытые имена функций.
import math
import fire
def pi(n):
s = 0.0
for i in range(n):
s += 1.0/(i+1)/(i+1)
return math.sqrt(6*s)
def fact(n):
s = 1
for i in range(n):
s *= (i+1)
return s
if __name__ == '__main__':
fire.Fire({
"pi[n]": pi
})
Мы только выставили функцию pi и изменили имя, запустили ее и увидели эффект
> python maths.py pi[n] 1000
3.14063805621
Если мы используем оригинальное имя функции, мы увидим понятное сообщение об ошибке, указанное огнем
> python maths.py pi 1000
Fire trace:
1. Initial component
2. ('Cannot find target in dict:', 'pi', {'pi[n]': <function pi at 0x10a062c08>})
Type: dict
String form: {'pi[n]': <function pi at 0x10a062c08>}
Length: 1
Usage: maths.py
maths.py pi[n]
открытый объект
import math
import fire
class Maths(object):
def pi(self, n):
s = 0.0
for i in range(n):
s += 1.0/(i+1)/(i+1)
return math.sqrt(6*s)
def fact(self, n):
s = 1
for i in range(n):
s *= (i+1)
return s
if __name__ == '__main__':
fire.Fire(Maths())
бегать
> python maths.py pi 1000
3.14063805621
> python maths.py fact 20
2432902008176640000
выставленный класс
Это мы продемонстрировали в реальной боевой ссылке выше, поэтому я не буду повторяться здесь.
класс против объекта
В приведенном выше примере мы обнаружили, что нет никакой разницы между раскрытием классов и раскрытием объектов, так что какой из них должен быть более элегантным? Это зависит от того, есть ли у конструктора класса параметры.Если это конструктор без параметров, то разницы между экспозицией класса и объекта нет, а если у конструктора класса есть параметры, то она будет другой. Преобразуйте его. Урок математики, добавьте коэффициент увеличения.
import math
import fire
class Maths(object):
def __init__(self, coeff):
self.coeff = coeff
def pi(self, n):
s = 0.0
for i in range(n):
s += 1.0/(i+1)/(i+1)
return self.coeff * math.sqrt(6*s)
def fact(self, n):
s = 1
for i in range(n):
s *= (i+1)
return self.coeff * s
if __name__ == '__main__':
fire.Fire(Maths)
Поскольку конструкторы Maths имеют параметры, вам необходимо указать значения параметров конструктора при запуске командной строки.
> python maths.py pi 1000 --coeff=2
6.28127611241
Если значение параметра не указано, время выполнения будет ошибка
> python maths.py pi 1000
Fire trace:
1. Initial component
2. ('The function received no value for the required argument:', 'coeff')
Type: type
String form: <class '__main__.Maths'>
File: ~/source/rollado/maths.py
Line: 5
Usage: maths.py COEFF
maths.py --coeff COEFF
Если он изменен на открытый объект, коэффициент увеличения жестко запрограммирован в коде, и настройка параметра не может быть выполнена в командной строке. В этом разница между открытыми объектами и открытыми классами, кажется, что открытые классы более мощные.
открытое имущество
Во всех приведенных выше примерах мы заканчиваем тем, что раскрываем функции либо в модулях, либо в классах. Но на самом деле огонь тоже может выставлять свойства, например, мы можем вывести указанный выше параметр coeff через командную строку.
> python maths.py coeff --coeff=2
2
> python maths.py coeff --coeff=3
3
Другой более простой пример
# example.py
import fire
english = 'Hello World'
spanish = 'Hola Mundo'
fire.Fire()
бегать
$ python example.py english
Hello World
$ python example.py spanish
Hola Mundo
принцип
Существует однозначное соответствие между порядком аргументов в командной строке и древовидной иерархией объектов в коде. Если fire выставляет текущий модуль без параметров, то первым параметром должно быть имя функции, имя класса или имя переменной внутри модуля. Если первый параметр является функцией, то следующие параметры являются параметрами функции. Если первый параметр является классом, то следующие параметры могут быть методами или полями внутри экземпляра этого класса. Если первым параметром является имя переменной и после него нет параметров, переменная будет отображаться напрямую. Если позади есть параметры, обработайте переменную как объект, а затем продолжайте использовать последующие параметры для более глубокого анализа объекта.
Все переменные в Python являются объектами, включая обычные целые числа, строки, числа с плавающей запятой, логические значения и т. д. Теоретически структура объекта может быть рекурсивно продолжена для формирования сложного связанного вызова.
цепная экспозиция
Далее мы проверяем эту теорию и пробуем комплексное цепное воздействие.
import fire
class Chain(object):
def __init__(self):
self.value = 1
def incr(self):
print "incr", self.value
self.value += 1
return self
def decr(self):
print "decr", self.value
self.value -= 1
return self
def get(self):
return self.value
if __name__ == '__main__':
fire.Fire(Chain)
запустить его
> python chains.py incr incr incr decr decr get
incr 1
incr 2
incr 3
decr 4
decr 3
2
Круто! Мы достигаем приятного эффекта цепочки, имея сам объект метода внутри каждого метода.
Далее мы пытаемся деконструировать встроенные строковые объекты.
# xyz.py
import fire
value = "hello"
if __name__ == '__main__':
fire.Fire()
Строки имеют верхний и нижний методы, мы многократно используем верхний и нижний, а затем наблюдаем за результатами.
> python xyz.py value
hello
> python xyz.py value upper
HELLO
> python xyz.py value upper lower
Traceback (most recent call last):
File "xyz.py", line 7, in <module>
fire.Fire()
File "/Users/pyloque/source/pys/.py/lib/python2.7/site-packages/fire/core.py", line 127, in Fire
component_trace = _Fire(component, args, context, name)
File "/Users/pyloque/source/pys/.py/lib/python2.7/site-packages/fire/core.py", line 366, in _Fire
component, remaining_args)
File "/Users/pyloque/source/pys/.py/lib/python2.7/site-packages/fire/core.py", line 542, in _CallCallable
result = fn(*varargs, **kwargs)
TypeError: upper() takes no arguments (1 given)
К сожалению, встроенный строковый объект, по-видимому, не поддерживает цепные вызовы, и первая верхняя строка выполняется успешно. Но огонь дает специальный символ для решения этой проблемы.
> python xyz.py value upper - lower
hello
> python xyz.py value upper - lower - upper
HELLO
> python xyz.py value upper - lower - upper - lower
hello
Знак минус используется для обозначения конца параметра, чтобы последующие параметры не отображались как параметры функции.
Пусть redis-py станет командной строкой за секунды
Наконец, давайте возьмем еще один классный небольшой пример, раскрывающий StrictRedis для redis-py и превращающий его в командную строку.
import fire
import redis
if __name__ == '__main__':
fire.Fire(redis.StrictRedis)
Это так просто, тогда вы можете играть с командной строкой
> python client.py flushdb
True
> python client.py set codehole superhero
True
> python client.py get codehole
superhero
> python client.py exists codehole
True
> python client.py keys "*"
codehole
> python client.py delete codehole
1
# 指定地址
> python client.py set codehole superhero --host=127.0.0.1 --port=6379
True
Суммировать
С такой небольшой библиотекой классов, как Google Fire, мы можем избавиться от сложного анализа параметров командной строки. Мы часто говорим, что написание кода должно быть красивым и элегантным, без хорошей библиотеки классов этого идеала достичь не очень просто. Если нет огня, у вас есть возможность попробовать красиво написать сложный код разбора параметров командной строки и показать учителю.
Читайте более продвинутые статьи, обратите внимание на паблик-аккаунт "Code Cave"