Python字符串插值实现

Python字符串插值实现,python,string-interpolation,Python,String Interpolation,[编辑00]:我已经编辑了几次这篇文章,现在连标题都改了,请看下面 我刚刚了解了format string方法,以及它在字典中的使用,比如vars()、locals()和globals(),例如: name = 'Ismael' print 'My name is {name}.'.format(**vars()) 但我想做: name = 'Ismael' print 'My name is {name}.' # Similar to ruby 所以我想到了这个: def mprint(s

[编辑00]:我已经编辑了几次这篇文章,现在连标题都改了,请看下面

我刚刚了解了format string方法,以及它在字典中的使用,比如
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)
您可以在此处与代码交互:

最后,我想做的是在另一个名为
my_print.py
的文件中使用该函数,以便执行以下操作:

from my_print import mprint

name= 'Ismael'
mprint('Hello! My name is {name}.')
但就目前而言,作用域存在一个问题,如何从导入的mprint函数中获取作为字典的主模块名称空间。(不是来自
my_print.py
的)

我希望我自己做了uderstood,如果没有,请尝试从另一个模块导入该函数。(回溯在链接中)

它正在从
my_print.py
访问
globals()
dict,但是当然变量名没有在该范围内定义,您知道如何实现吗

如果函数在同一个模块中定义,则该函数可以工作,但请注意我必须如何使用
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.
你们觉得呢,伙计们?那对我来说是一件困难的事

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


[编辑02]:我制作了一个带有
插值
函数的模块,一个
插值
类,并尝试了一个类似于该函数的
插值
类方法

它有一个小的测试套件和它的文档

我被方法实现卡住了,我不明白

代码如下:

你们觉得呢,伙计们


[编辑03]:好的,我现在只使用
interpolate()
函数

string\u 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,并描述了我发现的一些限制:

您可以在此处快速测试代码:

并在此处克隆grom git repo:
中突出显示了问题的一部分,也就是它不起作用的原因

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


虽然Ruby可能很方便,但如果您想充分利用Python语言,我建议您不要用Python编写Ruby。

模块在Python中不共享名称空间,因此
globals()
for
my_print
始终是my_print.py文件的
globals()
;i、 e实际定义函数的位置

def mprint(string='', dic = None):
    dictionary = dic if dic is not None else globals()
    print string.format(**dictionary)
您应该显式地传递当前模块的globals(),以使其工作

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

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

编辑:解决了这个问题

来自
string
模块的
Template
类也做了我需要的事情(但更类似于string
format
方法),最后它还具有我所寻求的可读性,它还具有推荐的明确性,它位于标准库中,并且可以轻松地进行定制和扩展

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

在此处运行代码:


我只想少打字我开始在我的脚本中大量使用成语
'.format(**vars())
,然后我意识到我必须重构它,所以我做了(尝试了),我真的不在乎它看起来是否像ruby,因为我直到最近才知道任何编程知识,但它对我来说仍然更具可读性,我经常使用它进行简单的格式化。我希望能够这样称呼它:
从我的打印导入mprint;名称='Ismael';mprint(‘你好!我的名字是{name}’)
没有globals,etc每次都打电话来,只是想知道怎么做,一定有办法!基本上,我想要实现的是将其作为默认行为:
mprint('Hello my name is{name}',vars())
而不每次显式调用vars()。谢谢你的链接!是否有一种方法可以将
main.py
的名称空间从,
my_print.py
获取为dict?我现在正在读关于继承的书,一个类点符号不会起作用吗?但那我就得让这个班可以打电话了?哈哈,我现在就到此为止,谢谢阿什维尼!从python文档:所以我需要从mprint内部获取main.py
\uuuu dict\uuuu
,这真的不可能吗?我无法停止思考这个问题。@user2374329您可以使用
main.\uu dict\uuu
,但它只包含导入
main
时定义的变量。顺便说一句,继承与类而不是模块有关。再次感谢,我完全迷路了。相关:相关:这是一个有趣的练习,但我要警告这种隐式行为:Python不鼓励它(“显式优于隐式”在这里意味着
mprint(“…”,vars())
优于
mprint(“…”)
返回调用者并获取其局部变量),我认为这样做是有充分理由的(显式代码可以说更易于阅读和修改)
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())