validar solo regulares python3 para metacaracter letras fechas expresiones ejemplos python anonymous-function lambda

solo - validar expresiones regulares en python



Elija la función de Python para llamar en función de una expresión regular (14)

¿Es posible poner una función en una estructura de datos, sin darle primero un nombre con 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?

El cuerpo de una función lambda está severamente limitado, así que no puedo usarlos.

Editar: para referencia, esto es más como el código de la vida real donde encontré el problema.

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) )


Como dijiste, esto no se puede hacer. Pero puedes aproximarte.

def create_printer(): def myprint(x): print x return myprint x = create_printer()

myprint es efectivamente anónimo aquí, ya que el alcance de la variable en el que fue creado ya no es accesible para la persona que llama. (Ver cierres en Python ).


Como todas las lambda mencionadas son la única forma, pero debes pensar no en las limitaciones de lambda sino en cómo evitarlas, por ejemplo, puedes usar listas, dictados, comprensiones y demás para hacer lo que quieras:

funcs = [lambda x,y: x+y, lambda x,y: x-y, lambda x,y: x*y, lambda x: x] funcs[0](1,2) >>> 3 funcs[1](funcs[0](1,2),funcs[0](2,2)) >>> -1 [func(x,y) for x,y in zip(xrange(10),xrange(10,20)) for func in funcs]

EDITADO con impresión (intente ver el módulo pprint ) y control-flujo:

add = True (funcs[0] if add else funcs[1])(1,2) >>> 3 from pprint import pprint printMsg = lambda isWarning, msg: pprint(''WARNING: '' + msg) if isWarning else pprint(''MSG:'' + msg)


Continuando con Gareth''s enfoque limpio Gareth''s con una solución autónoma modular:

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)


Esto se basa en la buena respuesta de Udi .

Creo que la dificultad de crear funciones anónimas es algo así como una pista falsa. Lo que realmente desea hacer es mantener juntos el código relacionado y hacer que el código sea claro. Entonces creo que los decoradores pueden funcionar para usted.

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


La única forma de hacer una función anónima es con lambda , y como sabes, solo pueden contener una sola expresión.

Puede crear varias funciones con el mismo nombre, de modo que al menos no tenga que pensar en nombres nuevos para cada una.

Sería genial tener funciones verdaderamente anónimas, pero la sintaxis de Python no puede soportarlas fácilmente.


La única opción es usar una expresión lambda, como mencionas. Sin eso, no es posible. Esa es la forma en que funciona Python.


No deberías hacerlo porque eval es malo, pero puedes compilar código de función en tiempo de ejecución usando FunctionType y 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.


Personalmente, simplemente lo nombraría algo, úsala y no te preocupes por "andar por ahí". Lo único que obtendrás al usar sugerencias como redefinirlo más tarde o usar del para quitar el nombre del espacio de nombres es una posibilidad de confusión o errores si alguien más tarde aparece y mueve algún código sin descifrar lo que eres obra.


Puede usar exec :

def define(arglist, body): g = {} exec("def anonfunc({0}):/n{1}".format(arglist, "/n".join(" {0}".format(line) for line in body.splitlines())), g) return g["anonfunc"] f_list = [define("msg", "print(msg)")] f_list[0](''hi'')


Python realmente, realmente no quiere hacer esto. No solo no tiene forma de definir una función anónima de varias líneas, sino que las definiciones de función no devuelven la función, por lo que incluso si esto fuera sintácticamente válido ...

mylist.sort(key=def _(v): try: return -v except: return None)

... todavía no funcionaría. (Aunque supongo que si fuera sintácticamente válido, harían que las definiciones de funciones devuelvan la función, por lo que funcionaría).

Entonces puede escribir su propia función para hacer una función a partir de una cadena (usando el exec por supuesto) y pasar una cadena citada por triples. Es un poco feo sintácticamente, pero funciona:

def function(text, cache={}): # strip everything before the first paren in case it''s "def foo(...):" if not text.startswith("("): text = text[text.index("("):] # keep a cache so we don''t recompile the same func twice if text in cache: return cache[text] exec "def func" + text func.__name__ = "<anonymous>" cache[text] = func return func # never executed; forces func to be local (a tiny bit more speed) func = None

Uso:

mylist.sort(key=function("""(v): try: return -v except: return None"""))


Si desea mantener un espacio de nombres limpio, use del:

def myprint(msg): print msg f_list = [ myprint ] del myprint f_list[0](''hi'')


Si le preocupa contaminar el espacio de nombres, cree sus funciones dentro de otra función. Entonces solo está "contaminando" el espacio de nombres local de la función create_functions y no el espacio de nombres externo.

def create_functions(): def myprint(msg): print msg return [myprint] f_list = create_functions() f_list[0](''hi'')


Si su función es lo suficientemente complicada como para no encajar en una función lambda , entonces, para mayor legibilidad, probablemente sería mejor definirla en un bloque normal de todos modos.


Una forma NICAD SECA de resolver su problema real:

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, ]]