【发布时间】:2013-05-06 11:09:01
【问题描述】:
[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的那个)
我希望我明白了,如果没有,请尝试从另一个模块导入该函数。 (回溯在链接中)
它正在从my_print.py 访问globals() dict,但是变量名当然没有在那个范围内定义,有什么想法可以做到这一点吗?
如果函数在同一个模块中定义,则该函数可以工作,但请注意我必须如何使用 globals(),因为如果不是,我只会获得包含 mprint() 范围内的值的字典。
我尝试过使用非本地和点符号来访问主要模块变量,但我仍然无法弄清楚。
[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)
再次感谢各位!有意见吗?
[编辑 04]:
这是我的最后一个版本,它有一个测试、文档字符串并描述了我发现的一些限制: http://pastebin.com/ssqbbs57
您可以在这里快速测试代码: http://labs.codecademy.com/BBMF#:workspace
并在此处克隆 grom git repo: https://github.com/Ismael-VC/python_string_interpolation.git
【问题讨论】:
-
这是一个有趣的练习,但我会警告这种隐式行为:Python 不鼓励它(“显式优于隐式”意味着
mprint('…', vars())比mprint('…')好回去到调用者并获取其局部变量),我认为这样做是有充分理由的(可以说,显式代码更容易阅读和维护)。 -
如果代码被正确记录,会有什么不同吗?
help(mprint)mprint([string[, dictionary]]) -> string'''plus concise docstring'''我对数据隐藏和界面设计的理解是调用者只需要知道调用的前提条件,行为是什么,它做了什么以及之后返回什么通话等。但不是如何实现的。我认为它可以说更容易阅读,更少的打字(错误),如果它被明确解释,它就不会是隐含的或神奇的。这个或任何其他包装器有什么区别?谢谢! -
顺便说一句,您可以使用
string.Formatterto accept an arbitrary mapping as.format_map()does 例如def mprint(.., _format=Formatter().format): ..
标签: python string-interpolation