Python字符串插值实现

[编辑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

我希望我自己理解,如果不是,请尝试从另一个模块导入函数。 (回溯在链接中)

它从my_print.py访问globals()字典,但是当然变量名没有在该范围中定义,有关如何完成此操作的任何想法?

如果函数在同一个模块中定义,那么该函数可以工作,但注意我必须使用globals()因为如果不是,我只会得到一个mprint()范围内的值的字典。

我试图使用nonlocal和点符号来访问主模块变量,但我仍然无法弄清楚。


[编辑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.

你们觉得怎么样? 对我来说这是一件困难的事情!

我喜欢它,对我更可读。


[编辑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)

再次感谢你们! 有什么意见?


[编辑04]:

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

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

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


模块不会在Python中共享名称空间,所以my_print globals()总是my_print.py文件的globals() ; 即该函数实际定义的位置。

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

您应该明确传递当前模块的全局变量()以使其工作。

Ans不使用可变对象作为python函数中的默认值,它可能会导致意外的结果。 改为使用“ None作为默认值。

一个理解模块范围的简单例子:

文件:my_print.py

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

文件:main.py

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

你的问题的一部分 - 呃,它不工作的原因 - 在这个问题中被强调。

您可以通过传递globals()作为第二个参数mprint('Hello my name is {name}',globals())来让你的函数工作。

尽管在Ruby中可能会很方便,但如果您想充分利用该语言,我鼓励您不要使用Python编写Ruby。


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

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

编辑: PEP-0498解决了这个问题!

来自string模块的Template类也做我所需要的(但更类似于字符串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

链接地址: http://www.djcxy.com/p/13335.html

上一篇: Python string interpolation implementation

下一篇: ExtJS Application Event Woes