2013-05-12 3 views
6

[EDIT 00]: Я редактировал несколько раз сообщение и теперь даже название, пожалуйста, прочитайте ниже.Реализация интерполяции строк Python

Я только что узнал о методе строки формата, и его использование со словарями, как те, предоставляемые 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)

Надеюсь, я сделал себе uderstood, если нет, попробуйте импортировать функцию из другого модуля. (трассировка находится в ссылке)

Он обращается к globals() dict от my_print.py, но, конечно, имя переменной не определено в этой области, любые идеи о том, как это сделать?

Функция работает, если она определена в том же модуле, но обратите внимание, как я должен использовать globals(), потому что, если нет, я бы получил только словарь со значениями в пределах mprint() scope.

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


[EDIT 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

Как вы думаете, ребята?


[EDIT 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]:

Это моя последняя версия, то есть тест, и описывает строки документации некоторые ограничения я нашел: http://pastebin.com/ssqbbs57

Вы можете быстро проверить код здесь : http://labs.codecademy.com/BBMF#:workspace

И клон Grom мерзавец репо здесь: https://github.com/Ismael-VC/python_string_interpolation.git

+2

связанно: [? Является ли строка форматирования, которая тянет переменную из своей вызывающей области видимости плохой практики] (http://stackoverflow.com/questions/13312240/is- a-string-formatter-that-pulls-variables-from-its-call-scope-bad-practice) – jfs

+1

related: [Печать имен и содержимого переменных в качестве инструмента отладки; ищет emacs/Python shortcut] (http://stackoverflow.com/questions/2813227/printing-variable-names-and-contents-as-debugging-tool-looking-for-emacs-python) – jfs

+0

Это интересное упражнение , но я предупреждал бы о таком неявном поведении: Python отговаривает его («Явный лучше, чем неявный» означает здесь, что 'mprint ('...', vars())' лучше, чем 'mprint ('...')' going обратно к вызывающему абоненту и получить его локальные переменные), и я думаю, что он по уважительным причинам (явный код, возможно, легче читать и поддерживать). – EOL

ответ

0

Язык дизайна не только разгадывать головоломки: ;)

http://www.artima.com/forums/flat.jsp?forum=106&thread=147358

Edit:PEP-0498 решает эту проблему!

Template класса от string модуля, а также делает то, что мне нужно (но больше похоже на метод строки format), в конце концов, он также имеет читаемость я ищу, он также имеет рекомендованную эксплицитность, это в стандарте Библиотека, а также легко настраивается и расширяется.

http://docs.python.org/2/library/string.html?highlight=template#string.Template

from string import Template 

name = 'Renata' 
place = 'hospital' 
job = 'Dr.' 
how = 'glad' 
header = '\nTo Ms. {name}:' 

letter = Template(""" 
Hello Ms. $name. 

I'm glad to inform, you've been 
accepted in our $place, and $job Red 
will ${how}ly recieve you tomorrow morning. 
""") 

print header.format(**vars()) 
print letter.substitute(vars()) 

Самое смешное, что теперь я все больше любил использовать {} вместо $ и я до сих пор, как модуль string_interpolation я придумал, потому что меньше набирать, чем любой из них в в долгосрочной перспективе. ЛОЛ!

Выполнить код здесь:

http://labs.codecademy.com/BE3n/3#:workspace

1

Часть вашей проблемы - ну, причина ее не работает - выделена в this question.

Вы можете использовать свою функцию, перейдя в globals() в качестве второго аргумента, mprint('Hello my name is {name}',globals()).

Хотя это может быть удобно в Ruby, я бы посоветовал вам не писать Ruby на Python, если вы хотите максимально использовать язык.

+0

Я просто хочу набрать менее реально! ;) Я начал использовать идиому '' '.format (** vars()) 'много в моих сценариях, затем я перепрофилировал, что мне пришлось реорганизовать это, поэтому я сделал (попробовал), мне все равно, выглядит как рубин или нет, так как до недавнего времени я ничего не знал о программировании, но все же он выглядит намного более удобочитаемым для меня, и я использую его для простого форматирования. Я хотел бы иметь возможность называть это следующим образом: 'from my_print import mprint; name = 'Ismael'; mprint ('Привет! Меня зовут {name}.') 'Без глобалов и т. д. каждый раз нужно просто знать, как это можно сделать, должен быть способ! – SalchiPapa

+0

В основном, что я хочу достичь, нужно сделать это по умолчанию: 'mprint ('Hello my name is {name}', vars())' без явного вызова vars() каждый раз.Спасибо за ссылку, кстати! – SalchiPapa

2

Модули не разделяют пространства имен в python, поэтому globals() для my_print всегда будет globals() файла my_print.py; в том месте, где функция была фактически определена.

def mprint(string='', dic = None): 
    dictionary = dic if dic is not None else globals() 
    print string.format(**dictionary) 

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

Ans не используют изменяемые объекты в качестве значений по умолчанию в функциях python, это может привести к unexpected results. Вместо этого используйте значение None.

Простой пример для понимания областей в модулях:

файл: my_print.py

x = 10 
def func(): 
    global x 
    x += 1 
    print x 

файла: главный.ру

from my_print import * 
x = 50 
func() #prints 11 because for func() global scope is still 
     #the global scope of my_print file 
print x #prints 50 
+0

Не существует способа получить пространство имен 'main.py' из' my_print.py' как dict? Я читаю о наследовании, прямо сейчас, не будет ли обозначение класса-точки зрения трюком? Но тогда мне придется сделать класс вызываемым ¿? LOL Я назову это днем, спасибо Ашвини! – SalchiPapa

+0

Из документов python: http://docs.python.org/2/library/functions.html#vars Так что мне нужно получить main.py '__dict__' изнутри mprint, действительно ли это невозможно? Я не могу перестать думать об этом. – SalchiPapa

+0

@ user2374329 Вы можете использовать 'main .__ dict__', но он будет содержать только переменные, которые были определены при импорте' main'. BTW Наследование связано с классами, а не с модулями. –