Python字符串插值实现

Sal*_*apa 7 python string-interpolation

[编辑00]:我已经多次编辑该帖子,现在甚至是标题,请阅读以下内容.

我只是了解了格式字符串的方法,其使用词典使用,如所提供的那些vars(),locals()globals(),例如:

name = 'Ismael'
print 'My name is {name}.'.format(**vars())
Run Code Online (Sandbox Code Playgroud)

但是我想这样做:

name = 'Ismael'
print 'My name is {name}.' # Similar to ruby
Run Code Online (Sandbox Code Playgroud)

所以我想出了这个:

def mprint(string='', dictionary=globals()):
    print string.format(**dictionary)
Run Code Online (Sandbox Code Playgroud)

您可以在此处与代码进行交互:http://labs.codecademy.com/BA0B/3#: workspace

最后,我想做的是将该函数放在另一个名为的文件中my_print.py,这样我就能做到:

from my_print import mprint

name= 'Ismael'
mprint('Hello! My name is {name}.')
Run Code Online (Sandbox Code Playgroud)

但就像现在一样,范围存在问题,我如何从导入的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)
Run Code Online (Sandbox Code Playgroud)

在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]}.")
Run Code Online (Sandbox Code Playgroud)

它打印:

Hello! My name is Ismael, I'm from Mexico
and I can speak Spanish and English.
Run Code Online (Sandbox Code Playgroud)

你们觉得怎么样?这对我来说很难!

我喜欢它,对我来说更具可读性.


[编辑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)
Run Code Online (Sandbox Code Playgroud)

再次感谢你们!任何意见?


[编辑04]:

这是我的最后一个版本,它有一个测试,docstrings并描述了我发现的一些限制:http: //pastebin.com/ssqbbs57

您可以在此处快速测试代码:http://labs.codecademy.com/BBMF#: workspace

并在这里克隆grom git repo:https: //github.com/Ismael-VC/python_string_interpolation.git

Sal*_*apa 0

语言设计不仅仅是解决难题:;)

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

编辑: 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())
Run Code Online (Sandbox Code Playgroud)

有趣的是,现在我越来越喜欢使用{}而不是,$而且我仍然喜欢string_interpolation我想出的模块,因为从长远来看,它比任何一个模块都要少打字。哈哈!

在这里运行代码:

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