__slots__
Python中的目的是什么- 特别是关于我何时想要使用它,何时不想使用它?
我正在使用模板字符串来生成一些文件,我喜欢为此目的的新f字符串的简洁性,以减少我之前的模板代码,如下所示:
template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
print (template_a.format(**locals()))
Run Code Online (Sandbox Code Playgroud)
现在我可以这样做,直接替换变量:
names = ["foo", "bar"]
for name in names:
print (f"The current name is {name}")
Run Code Online (Sandbox Code Playgroud)
但是,有时在其他地方定义模板是有意义的 - 在代码中更高,或从文件或其他东西导入.这意味着模板是一个带有格式标签的静态字符串.必须在字符串上发生一些事情,告诉解释器将字符串解释为新的f字符串,但我不知道是否有这样的事情.
有没有办法引入一个字符串并将其解释为f字符串以避免使用该.format(**locals())
调用?
理想情况下,我希望能够像这样编码......(magic_fstring_function
我不理解的部分在哪里进来):
template_a = f"The current name is {name}"
# OR [Ideal2] template_a = magic_fstring_function(open('template.txt').read())
names = ["foo", "bar"]
for name in names:
print (template_a)
Run Code Online (Sandbox Code Playgroud)
...使用此期望的输出(不读取文件两次):
The current name is foo
The current name is bar
Run Code Online (Sandbox Code Playgroud)
...但我得到的实际输出是:
The current …
Run Code Online (Sandbox Code Playgroud) 使用格式字符串+ args列表与格式内联调用日志记录函数是否有利?
我已经看过(并写过)使用内联字符串格式的日志代码:
logging.warn("%s %s %s" % (arg1, arg2, arg3))
Run Code Online (Sandbox Code Playgroud)
但我认为使用它更好(性能方面,更具惯用性):
logging.warn("%s %s %s", arg1, arg2, arg3)
Run Code Online (Sandbox Code Playgroud)
因为第二种形式在调用日志记录功能之前避免了字符串格式化操作.如果当前日志记录级别将过滤掉日志消息,则不需要格式化,从而减少了计算时间和内存分配.
我在这里是正确的轨道,还是我错过了什么?
Python有几种打印"跟踪"输出的方法.print
,import logging
,stdout.write
可用于打印调试信息,但他们都有一个缺点:即使记录仪的门槛太高或流被关闭,Python将仍然评估参数的print语句.(严格评估)这可能会花费字符串格式或更多.
显而易见的解决方法是将字符串创建代码放入lambda中,并使用我们自己的日志记录函数有条件地调用lambda(这个检查__debug__
内置变量,每当python启动-O
优化时设置为False ):
def debug(f):
if __debug__:
print f()
#stdout.write(f())
#logging.debug(f())
for currentItem in allItems:
debug(lambda:"Working on {0}".format(currentItem))
Run Code Online (Sandbox Code Playgroud)
优点是不调用str(currentItem)
和string.format
发布版本,缺点是必须lambda:
在每个日志记录语句中键入.
Python的assert
语句由Python编译器专门处理.如果运行python -O
,则丢弃任何断言语句而不进行任何评估.您可以利用它来制作另一个有条件评估的日志记录语句:
assert(logging.debug("Working on {0}".format(currentItem)) or True)
Run Code Online (Sandbox Code Playgroud)
启动Python时,不会评估此行-O
.
短路运营商'和'和'或'甚至可以使用:
__debug__ and logging.debug("Working on {0}".format(currentItem));
Run Code Online (Sandbox Code Playgroud)
但是现在我们最多有28个字符加上输出字符串的代码.
我要问的问题:是否有任何标准的python语句或函数具有与语句相同的条件评估属性assert
?或者,有没有人有这里提出的方法的任何替代方案?
我有一些像这样的python:
def foo():
logger = logging.getLogger()
# do something here
logger.debug('blah blah {}'.format(expensive_func()))
foo()
Run Code Online (Sandbox Code Playgroud)
where expensive_func()
是一个返回字符串的函数,执行起来很昂贵.
在开发时,日志级别设置为DEBUG,并且expensive_func()
执行,消息被记录,一切都很好.
问题是,当我将日志级别设置为严格大于DEBUG(例如WARNING)时,在生产环境中,显然返回值expensive_func()
不会被记录,但昂贵的函数本身仍将被执行.
我的问题是:当日志记录级别为WARNING时,如何防止python出现昂贵的函数?
我不想删除该调试行或添加像if level > DEBUG: return
昂贵的功能.
谢谢.
编辑
我刚刚访问了懒惰记录器消息字符串评估,但不满意,主要是因为:
class Lazy:
def __init__(self, func, *a, **ka):
self.func= func
self.a = a
self.ka= ka
def __str__(self):
return str(self.func(*self.a, **self.ka))
# Though this is ugly, it works
logger.debug('Message: %s', Lazy(expensive_func))
# What if I wanted to do this?
# logger.debug('Message: {}'.format(expf_1(expf_2(some_arg))))
# Maybe …
Run Code Online (Sandbox Code Playgroud) 我必须将代码从 Python2.x 转换为 Python3 (主要是字符串格式)我遇到了这样的事情:
Logger.info("random String %d and %i".format(value1, value2))
Run Code Online (Sandbox Code Playgroud)
现在,我知道 %d 可以替换为 {:d} 但无法使用 {:i} 找到与 %i (带符号)等效的内容,并出现以下错误:
ValueError:类型“int”的对象的未知格式代码“i”
是否有可能在Python中实现以下(伪)代码的等价物?
#define DEBUG(topic, msg) LOG_IMPL(Logger.DEBUG, topic, msg)
#define INFO(topic, msg) LOG_IMPL(Logger.INFO, topic, msg)
#define LOG_IMPL(level, topic, msg) if(Logger.level() <= level) { Logger.log(level, topic, msg); }
DEBUG("MyComponent", "What you logging at?")
Run Code Online (Sandbox Code Playgroud)
这里的好处是你不必评估字符串日志消息,例如连接字符串,调用.format()等.)
更新:
懒惰的记录器消息字符串评估 - 这回答了我的问题所以我将投票结束这篇文章.
这两个电话之间有什么区别:
import logging
logging.getLogger().debug('test: %i' % 42)
Run Code Online (Sandbox Code Playgroud)
和
logging.getLogger().debug('test: {}'.format(42))
Run Code Online (Sandbox Code Playgroud)
我们假设42
在被投射到字符串(例如750万年)时会被一些长计算所取代,产生最终答案为42.
在将日志记录设置为调试的情况下,是否对前一种方法进行了延迟评估?
python ×9
logging ×5
oop ×2
python-3.x ×2
c++ ×1
coding-style ×1
debugging ×1
f-string ×1
idioms ×1
macros ×1
metaclass ×1
python-3.6 ×1
slots ×1
string ×1