</> Cómo funciona
Función pura del español.
| parámetro | tipo | por defecto | qué hace |
|---|---|---|---|
palabra | string | — (obligatorio) | la palabra en femenino |
categoria | string | opcional | `Adjetivos` para respetar invariantes |
singular | boolean | True | `false` si la entrada es plural |
commons/masculinizador.py → clase Masculinizador con masculinizar().upln) para las ramas -na/-sa (leona → león, condesa → conde), y el detector de género por terminación para respetar los invariantes.flowchart TD
MOD[("repositorio")]
__init__["__init__()"]
desde_dir["🔒 desde_dir()"]
masculinizar["masculinizar()"]
_load["🔒 _load()"]
desde_dir --> _load
__init__ -. datos .-> MOD
masculinizar -. datos .-> MOD
_load -. datos .-> MOD
classDef red fill:#fde7f0,stroke:#c0397b,color:#7a1e4d;
class desde_dir,_load,MOD red;# -*- coding: utf-8 -*-
"""
masculinizador.py — saca el masculino de una palabra en femenino (la operación REVERSA).
Ir de femenino a masculino es a veces AMBIGUO (devuelve varias opciones separadas por
coma). Uso típico: normalizar una entrada a su forma canónica.
Algoritmo, en pasos: 1) excepciones curadas 2) adjetivo de número invariable (a→o)
3) ¿ya es masculino / invariante? 4) reglas por terminación (-ta / -na / -sa / -ra +
general a→o). Se apoya en el silabeador/acentuador algorítmico (upln).
"""
import json
import os
import upln
try:
import genero as _genero
except Exception:
_genero = None
class Masculinizador:
def __init__(self, excepciones=None, mapa_aq0fn0=None, mapa_masculino=None,
usar_detector_genero=True):
self.excepciones = excepciones or {} # {femenino: masculino} curadas
self.mapa_aq0fn0 = mapa_aq0fn0 or {} # adjetivo femenino de número invariable -> a→o
self.mapa_masculino = mapa_masculino or {} # ya masculino / invariante -> se devuelve igual
self.usar_detector_genero = usar_detector_genero and _genero is not None
@classmethod
def desde_dir(cls, d):
"""Construye el masculinizador cargando sus tablas de léxico."""
# […carga de excepciones y mapas del repositorio léxico (ficheros y esquema, internos)…]
return cls(excepciones=exc,
mapa_aq0fn0={w: True for w in aq},
mapa_masculino={w: True for w in invar})
def masculinizar(self, femenino, es_singular=True, categoria=None):
if femenino is None:
return None
femenino = femenino.lower().strip()
if femenino == "":
return ""
if femenino in self.excepciones: # 1. excepciones curadas (reina→rey)
return self.excepciones[femenino]
if femenino in self.mapa_aq0fn0: # 2. adjetivo invariable de número: a→o
return upln.remplace_last("a", "o", femenino)
if femenino in self.mapa_masculino: # 3. ya masculino / invariante
return femenino
# adjetivos comunes (C) por terminación: no tienen masculino distinto
if (self.usar_detector_genero and categoria
and str(categoria).lower().startswith("adj")
and _genero.es_invariable(femenino)):
return femenino
if es_singular:
if not femenino.endswith("a"): # no acaba en 'a' -> ya es masculino
return femenino
# 4. acaba en 'a': reglas por terminación
sil = upln.silabear(femenino)
pos = upln.int_silaba_tonica(sil)
if pos == 1: # aguda -> misma palabra
return femenino
dos = femenino[-2:]
if dos == "ta":
# -eta/-anta/-enta/-ota admiten -e y -o (poeta→poete/poeto); resto a→o.
if femenino.endswith(("eta", "anta", "enta", "ota")):
return upln.remplace_last("a", "e", femenino) + "," + upln.remplace_last("a", "o", femenino)
return upln.remplace_last("a", "o", femenino)
if dos == "na":
# -ana/-ina/-ona/-una: a→o y además la variante en -n (leona→león).
if femenino[-3:] in ("ana", "ina", "ona", "una"):
r = upln.remplace_last("a", "o", femenino)
sil2 = upln.remplace_last(upln.SEPARADOR + "na", "n", sil)
return r + "," + upln.acentuar_silabeada(sil2, pos - 1)
return upln.remplace_last("a", "o", femenino)
if dos == "sa":
# -esa: a→o y variante en -s (condesa→condes / conde por excepción).
if femenino[-3:] == "esa":
r = upln.remplace_last("a", "o", femenino)
sil2 = upln.remplace_last(upln.SEPARADOR + "sa", "s", sil)
return r + "," + upln.acentuar_silabeada(sil2, pos - 1)
return upln.remplace_last("a", "o", femenino)
if dos == "ra":
# -dora/-ñora/-sora/-tora/-xora: se quita la 'a' (profesora→profesor).
if femenino[-4:] in ("dora", "ñora", "sora", "tora", "xora"):
return upln.remplace_last("a", "", femenino)
return upln.remplace_last("a", "o", femenino)
return upln.remplace_last("a", "o", femenino) # caso general a→o
else: # plural
if femenino.endswith("zas"):
return upln.remplace_last("zas", "ces", femenino) + "," + upln.remplace_last("zas", "zos", femenino)
if femenino.endswith("as"):
return upln.remplace_last("as", "es", femenino) + "," + upln.remplace_last("as", "os", femenino)
return femenino
if __name__ == "__main__":
# […pruebas del módulo (casos de ejemplo y comprobación)…]
Llámala con el código a la vista.
curl "https://api.wordkers.com/v1/masculinizar" \
-H "X-API-Key: TU_CLAVE"