Comportamiento extraño con las expresiones regulares de Python: findall solo encuentra la parte “()?”

Actualmente estoy escribiendo una expresión regular para encontrar las unidades y el tamaño (o podría funcionar como dimensiones) en una cadena. Por ejemplo: “Producto: A, 2 botellas de 3.5 galones”

Para simplificar, estoy eliminando todos los espacios en blanco, por lo que esto se convierte en:

“Producto: A, 2×3.5gallonbottles”

Mi expresión regular es la siguiente:

numAndSize = re.compile(r'\d+[xX]\d+(\.\d+)?') 

Pero cuando trato de usar findall, esto sucede:

 In [47]: numAndSize.findall("Product:A,2x3.5gallonbottles") Out[47]: ['.5'] 

Yo, solo, obtengo el ‘.5’ en esta cadena, en lugar de la expresión completa

Usando búsqueda y grupo, sin embargo, funciona como se espera:

 In [50]: numAndSize.search("Product:A,2x3.5gallonbottles").group(0) Out[50]: '2x3.5' 

A partir de ahí, intenté cambiar mi expresión regular para no incluir el decimal opcional, y encontré Findall en eso.

 In [51]: numAndSize = re.compile(r'\d+[xX]\d+') In [52]: numAndSize.findall("Product:A,2x3.5gallonbottles") Out[52]: ['2x3'] 

¿Hay alguna razón detrás de este comportamiento? Para mis propósitos, ciertamente puedo usar .search (). Group (), pero personalmente me gusta findall ya que la salida devuelve mucha más información en un formato limpio.

Si la expresión regular contiene grupos de captura, re.findall() devolverá esos grupos en lugar de la coincidencia completa. Para obtener la partida completa, use un grupo que no capture:

 >>> numAndSize = re.compile(r'\d+[xX]\d+(?:\.\d+)?') >>> numAndSize.findall("Product:A,2x3.5gallonbottles") ['2x3.5'] 

O si podría aprovechar este comportamiento para que devuelva una tupla de las dimensiones (o unidades o lo que sea):

 >>> numAndSize = re.compile(r'(\d+)[xX](\d+(?:\.\d+)?)') >>> numAndSize.findall("Product:A,2x3.5gallonbottles") [('2', '3.5')] 

Está creando un grupo de captura usando () . La documentación dice

Si uno o más grupos están presentes en el patrón, devuelva una lista de grupos; esta será una lista de tuplas si el patrón tiene más de un grupo.

Si realmente no desea capturar la parte fraccionaria, use un grupo que no capture:

 numAndSize = re.compile(r'\d+[xX]\d+(?:\.\d+)?')