Tim*_*Tim 54 python lambda anonymous-function
是否可以将函数放在数据结构中,而不是先给它命名def?
# This is the behaviour I want. Prints "hi".
def myprint(msg):
print msg
f_list = [ myprint ]
f_list[0]('hi')
# The word "myprint" is never used again. Why litter the namespace with it?
Run Code Online (Sandbox Code Playgroud)
lambda函数的主体受到严格限制,所以我不能使用它们.
编辑:作为参考,这更像是我遇到问题的现实代码.
def handle_message( msg ):
print msg
def handle_warning( msg ):
global num_warnings, num_fatals
num_warnings += 1
if ( is_fatal( msg ) ):
num_fatals += 1
handlers = (
( re.compile( '^<\w+> (.*)' ), handle_message ),
( re.compile( '^\*{3} (.*)' ), handle_warning ),
)
# There are really 10 or so handlers, of similar length.
# The regexps are uncomfortably separated from the handler bodies,
# and the code is unnecessarily long.
for line in open( "log" ):
for ( regex, handler ) in handlers:
m = regex.search( line )
if ( m ): handler( m.group(1) )
Run Code Online (Sandbox Code Playgroud)
Gar*_*ees 39
这是基于Udi的好答案.
我认为创建匿名函数的难度有点像红鲱鱼.你真正想做的是将相关代码保持在一起,并使代码整洁.所以我认为装饰师可能适合你.
import re
# List of pairs (regexp, handler)
handlers = []
def handler_for(regexp):
"""Declare a function as handler for a regular expression."""
def gethandler(f):
handlers.append((re.compile(regexp), f))
return f
return gethandler
@handler_for(r'^<\w+> (.*)')
def handle_message(msg):
print msg
@handler_for(r'^\*{3} (.*)')
def handle_warning(msg):
global num_warnings, num_fatals
num_warnings += 1
if is_fatal(msg):
num_fatals += 1
Run Code Online (Sandbox Code Playgroud)
Udi*_*Udi 16
更好的DRY方式来解决您的实际问题:
def message(msg):
print msg
message.re = '^<\w+> (.*)'
def warning(msg):
global num_warnings, num_fatals
num_warnings += 1
if ( is_fatal( msg ) ):
num_fatals += 1
warning.re = '^\*{3} (.*)'
handlers = [(re.compile(x.re), x) for x in [
message,
warning,
foo,
bar,
baz,
]]
Run Code Online (Sandbox Code Playgroud)
Udi*_*Udi 14
使用模块化自包含解决方案继续Gareth的清洁方法:
import re
# in util.py
class GenericLogProcessor(object):
def __init__(self):
self.handlers = [] # List of pairs (regexp, handler)
def register(self, regexp):
"""Declare a function as handler for a regular expression."""
def gethandler(f):
self.handlers.append((re.compile(regexp), f))
return f
return gethandler
def process(self, file):
"""Process a file line by line and execute all handlers by registered regular expressions"""
for line in file:
for regex, handler in self.handlers:
m = regex.search(line)
if (m):
handler(m.group(1))
# in log_processor.py
log_processor = GenericLogProcessor()
@log_processor.register(r'^<\w+> (.*)')
def handle_message(msg):
print msg
@log_processor.register(r'^\*{3} (.*)')
def handle_warning(msg):
global num_warnings, num_fatals
num_warnings += 1
if is_fatal(msg):
num_fatals += 1
# in your code
with open("1.log") as f:
log_processor.process(f)
Run Code Online (Sandbox Code Playgroud)
Udi*_*Udi 13
如果要保持干净的命名空间,请使用del:
def myprint(msg):
print msg
f_list = [ myprint ]
del myprint
f_list[0]('hi')
Run Code Online (Sandbox Code Playgroud)
如你所说,这是不可能做到的.但你可以近似它.
def create_printer():
def myprint(x):
print x
return myprint
x = create_printer()
Run Code Online (Sandbox Code Playgroud)
myprint这里实际上是匿名的,因为调用者无法再访问创建它的变量范围.(参见Python中的闭包.)
如果您担心污染命名空间,请在另一个函数内创建函数.然后你只是"污染" create_functions函数的本地命名空间而不是外部命名空间.
def create_functions():
def myprint(msg):
print msg
return [myprint]
f_list = create_functions()
f_list[0]('hi')
Run Code Online (Sandbox Code Playgroud)
你不应该这样做,因为 eval 是邪恶的,但你可以在运行时使用FunctionTypeand编译函数代码compile:
>>> def f(msg): print msg
>>> type(f)
<type 'function'>
>>> help(type(f))
...
class function(object)
| function(code, globals[, name[, argdefs[, closure]]])
|
| Create a function object from a code object and a dictionary.
| The optional name string overrides the name from the code object.
| The optional argdefs tuple specifies the default argument values.
| The optional closure tuple supplies the bindings for free variables.
...
>>> help(compile)
Help on built-in function compile in module __builtin__:
compile(...)
compile(source, filename, mode[, flags[, dont_inherit]]) -> code object
Compile the source string (a Python module, statement or expression)
into a code object that can be executed by the exec statement or eval().
The filename will be used for run-time error messages.
The mode must be 'exec' to compile a module, 'single' to compile a
single (interactive) statement, or 'eval' to compile an expression.
The flags argument, if present, controls which future statements influence
the compilation of the code.
The dont_inherit argument, if non-zero, stops the compilation inheriting
the effects of any future statements in effect in the code calling
compile; if absent or zero these statements do influence the compilation,
in addition to any features explicitly specified.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40225 次 |
| 最近记录: |