</> Cómo funciona
Función pura del español.
| parámetro | tipo | por defecto | qué hace |
|---|---|---|---|
palabra | string | — (obligatorio) | el adjetivo masculino a feminizar |
categoria | string | opcional | pon `Adjetivos` para respetar los invariantes (recomendado) |
singular | boolean | True | `false` si la entrada es plural |
commons/feminizador.py → clase Feminizador con feminizar().upln) para la rama -n/-s (campeón → campeona), y el detector de género por terminación para respetar los invariantes (masticable, cantante).flowchart TD
MOD[("repositorio")]
__init__["__init__()"]
desde_json["🔒 desde_json()"]
desde_dir["🔒 desde_dir()"]
feminizar["feminizar()"]
_load["🔒 _load()"]
desde_dir --> _load
__init__ -. datos .-> MOD
desde_json -. datos .-> MOD
feminizar -. datos .-> MOD
_load -. datos .-> MOD
classDef red fill:#fde7f0,stroke:#c0397b,color:#7a1e4d;
class desde_json,desde_dir,_load,MOD red;# -*- coding: utf-8 -*-
"""
feminizador.py — saca el femenino de un lema/palabra en masculino.
Algoritmo, en tres pasos: 1) excepciones curadas 2) ¿ya es femenino? (léxico) 3) reglas por sufijo.
La rama -n/-s usa el silabeador/acentuador algorítmico (upln.py), ya validado 100%.
Datos:
- excepciones curadas masculino→femenino + mapas de invariantes (del repositorio léxico).
Uso:
from feminizador import Feminizador
fem = Feminizador.desde_dir(directorio)
fem.feminizar("niño") -> "niña"
fem.feminizar("campeón") -> "campeona"
fem.feminizar("rey") -> "reina" (excepción)
"""
import json
import os
import upln
try:
import genero as _genero
except Exception:
_genero = None
class Feminizador:
def __init__(self, excepciones=None, mapa_femenino=None, mapa_aq0mn0=None,
usar_detector_genero=True):
# excepciones: {masculino: resultado} (resultado puede llevar varias sep. por coma)
self.excepciones = excepciones or {}
# mapa_femenino: palabras que YA son femeninas (invariantes) -> se devuelven igual
self.mapa_femenino = mapa_femenino or {}
# mapa_aq0mn0: adjetivos masculinos de número invariable -> o→a
self.mapa_aq0mn0 = mapa_aq0mn0 or {}
# detector de género por terminación: si es común (C) -> invariante, no se feminiza
self.usar_detector_genero = usar_detector_genero and _genero is not None
@classmethod
def desde_json(cls, ruta):
# […lectura del repositorio de excepciones…]
return cls(excepciones=exc)
@classmethod
def desde_dir(cls, directorio):
"""Carga excepciones + mapas de léxico (invariante / AQ0MN0) si existen."""
# […carga de excepciones y mapas del repositorio léxico (ficheros y esquema, internos)…]
return cls(
excepciones=exc,
mapa_femenino={w: True for w in invar},
mapa_aq0mn0={w: True for w in aq0mn0},
)
def feminizar(self, masculino, es_singular=True, categoria=None):
"""Devuelve el femenino de `masculino`. Para un LEMA, es_singular=True.
`categoria`: si es 'Adjetivos' (o adj...), se usa el detector de género por
terminación para respetar los invariantes (masticable, cantante). En sustantivos
NO se aplica (usan otra tabla de terminaciones)."""
if masculino is None:
return None
masculino = masculino.lower().strip()
if masculino == "":
return ""
# 1. excepciones curadas
if masculino in self.excepciones:
return self.excepciones[masculino]
# 2. ya es femenino / invariante en el léxico
if masculino in self.mapa_femenino:
return masculino
# 2bis. detector de género por terminación (SOLO adjetivos): común (C) -> invariante
if (self.usar_detector_genero and categoria
and str(categoria).lower().startswith("adj")
and _genero.es_invariable(masculino)):
return masculino
# adjetivo masculino de número invariable -> o→a
if masculino in self.mapa_aq0mn0:
return upln.remplace_last("o", "a", masculino)
# 3. reglas por sufijo
if es_singular:
if masculino.endswith("que"):
return upln.remplace_last("que", "ca", masculino)
if masculino.endswith("ge"):
return upln.remplace_last("ge", "ja", masculino)
if masculino.endswith("gue"):
return upln.remplace_last("gue", "ga", masculino)
if masculino.endswith("güe"):
return upln.remplace_last("güe", "gua", masculino)
if masculino.endswith("e") or masculino.endswith("o"):
return masculino[:-1] + "a"
if masculino.endswith(("r", "z", "l")):
return masculino + "a"
if masculino.endswith(("n", "s")):
sil = upln.silabear(masculino)
pos = upln.int_silaba_tonica(sil)
last = masculino[-1]
r = upln.remplace_last(last, upln.SEPARADOR + last + "a", sil)
r = upln.desacentuar_palabra(r)
try:
r = upln.acentuar_silabeada(r, pos + 1)
except Exception:
r = r.replace(upln.SEPARADOR, "")
return r
return masculino # invariante
else: # plural
if masculino.endswith("ques"):
return upln.remplace_last("ques", "cas", masculino)
if masculino.endswith("ges"):
return upln.remplace_last("ges", "jas", masculino)
if masculino.endswith("gues"):
return upln.remplace_last("gues", "guas", masculino)
if masculino.endswith("gües"):
return upln.remplace_last("gües", "gas", masculino)
if masculino.endswith("ces"):
return upln.remplace_last("ces", "zas", masculino)
if masculino.endswith("es"):
return upln.remplace_last("es", "as", masculino)
if masculino.endswith("os"):
return upln.remplace_last("os", "as", masculino)
return masculino
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/feminizar" \
-H "X-API-Key: TU_CLAVE"