[EDIT 00]: я редактировал несколько раз сообщение и теперь даже название, пожалуйста, прочитайте ниже.
Я только что узнал о методе строковых форматов и его использовании со словарями, таких как vars()
, locals()
и globals()
, например:
name = 'Ismael'
print 'My name is {name}.'.format(**vars())
Но я хочу:
name = 'Ismael'
print 'My name is {name}.' # Similar to ruby
Итак, я придумал это:
def mprint(string='', dictionary=globals()):
print string.format(**dictionary)
Вы можете взаимодействовать с кодом здесь: http://labs.codecademy.com/BA0B/3#:workspace
Наконец, мне бы хотелось, чтобы функция была в другом файле с именем my_print.py
, поэтому я мог сделать:
from my_print import mprint
name= 'Ismael'
mprint('Hello! My name is {name}.')
Но как сейчас, есть проблема с областями, как я могу получить пространство имен основного модуля в качестве словаря из импортированной функции mprint. (а не от my_print.py
)
Надеюсь, я заставил себя удержаться, если нет, попробуйте импортировать функцию из другого модуля. (трассировка находится в ссылке)
Он обращается к globals()
dict от my_print.py
, но, конечно, имя переменной не определено в этой области, любые идеи о том, как это сделать?
Функция работает, если она определена в том же модуле, но заметьте, как я должен использовать globals()
, потому что если бы я не получил только словарь со значениями в пределах mprint()
.
Я попытался использовать нелокальную и точечную нотацию для доступа к основным переменным модуля, но я все еще не могу понять.
[РЕДАКТИРОВАТЬ 01]: Думаю, я понял решение:
В my_print.py:
def mprint(string='',dictionary=None):
if dictionary is None:
import sys
caller = sys._getframe(1)
dictionary = caller.f_locals
print string.format(**dictionary)
В test.py:
from my_print import mprint
name = 'Ismael'
country = 'Mexico'
languages = ['English', 'Spanish']
mprint("Hello! My name is {name}, I'm from {country}\n"
"and I can speak {languages[1]} and {languages[0]}.")
Он печатает:
Hello! My name is Ismael, I'm from Mexico
and I can speak Spanish and English.
Как вы думаете, ребята? Это было сложно для меня!
Мне это нравится, гораздо читабельнее для меня.
[EDIT 02]: Я создал модуль с функцией interpolate
, класс interpolate
и попытку для метода класса interpolate
, аналогичного функции.
Он имеет небольшой набор тестов и документирован!
Я застрял в реализации метода, я не понимаю.
Здесь код: http://pastebin.com/N2WubRSB
Как вы думаете, ребята?
[ИЗМЕНИТЬ 03]: Хорошо. Я решил использовать только функцию interpolate()
.
В string_interpolation.py
:
import sys
def get_scope(scope):
scope = scope.lower()
caller = sys._getframe(2)
options = ['l', 'local', 'g', 'global']
if scope not in options[:2]:
if scope in options[2:]:
return caller.f_globals
else:
raise ValueError('invalid mode: {0}'.format(scope))
return caller.f_locals
def interpolate(format_string=str(),sequence=None,scope='local',returns=False):
if type(sequence) is str:
scope = sequence
sequence = get_scope(scope)
else:
if not sequence:
sequence = get_scope(scope)
format = 'format_string.format(**sequence)'
if returns is False:
print eval(format)
elif returns is True:
return eval(format)
Еще раз спасибо ребятам! Любые мнения?
[EDIT 04]:
Это моя последняя версия, у нее есть тест, docstrings и описаны некоторые ограничения, которые я нашел: http://pastebin.com/ssqbbs57
Вы можете быстро протестировать код здесь: http://labs.codecademy.com/BBMF#:workspace
И клонировать grom git repo здесь: https://github.com/Ismael-VC/python_string_interpolation.git