扩展星盘
用插件给 Astrolabe 类挂自定义分析方法。
斗数的分析规则千人千面,库不可能穷举。x-iztro 让你把自己的规则 以方法的形式挂到星盘类上——调用语法与内置方法一致,所有星盘实例都能用。
配方
一个插件就是一个函数,接受 Astrolabe 类并往上挂方法。
写一个接受
type[Astrolabe] 的函数在函数体里定义方法,赋值到类上
调
load_plugin 加载from x_iztro import Astro, Astrolabe, PalaceName
from x_iztro.plugin import load_plugin
def my_analysis(cls: type[Astrolabe]) -> None:
"""给星盘补两个自定义分析方法。"""
def major_star(self) -> str:
"""命宫主星名(空宫借对宫),多颗以逗号分隔"""
soul = self.palace(PalaceName.SOUL)
source = soul.opposite_palace() if soul.is_empty() else soul
return ",".join(s.name for s in source.major_stars)
def five_elements_value(self) -> int:
"""五行局的局数"""
return int(self.five_elements_class_key[-3])
cls.major_star = major_star
cls.five_elements_value = five_elements_value
load_plugin(my_analysis)用法
chart = Astro().by_solar("2000-8-16", 2, "female")
print(chart.major_star())
# 扩展方法随排盘语言输出
en = Astro().by_solar("2000-8-16", 2, "female", language="en-US")
print(en.major_star())输出
紫微
emperorload_plugin / load_plugins
签名
def load_plugin(plugin: Plugin) -> None
def load_plugins(plugins: Iterable[Plugin]) -> NonePlugin 的类型是 Callable[[type[Astrolabe]], None]。
参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
plugin | Plugin | 是 | — | 接受 Astrolabe 类的函数 |
plugins | Iterable[Plugin] | 是 | — | 按顺序加载的多个插件 |
返回值 None。方法直接挂到类上。
边界与陷阱
为什么能挂上去
Astrolabe 是 slots=True 的 frozen dataclass,实例上挂不了属性:
try:
chart.foo = 1
except Exception as e:
print(type(e).__name__, e)输出
FrozenInstanceError cannot assign to field 'foo'但类上挂方法不受影响。这正是插件需要的粒度: 插件改的是「所有星盘都有这个方法」,不是「这一张盘多了个字段」。
扩展别的类型
同一套写法适用于宫位与星耀,直接给对应的类挂方法即可:
from x_iztro.models import Palace
def palace_analysis(cls: type[Palace]) -> None:
def is_afflicted(self) -> bool:
"""本宫是否「煞忌交冲」:坐煞星且带化忌"""
sha = ["qingyangMin", "tuoluoMin", "huoxingMin",
"lingxingMin", "dikongMin", "dijieMin"]
return self.has_one_of(sha) and self.has_mutagen("sihuaJi")
cls.is_afflicted = is_afflicted
palace_analysis(Palace)for p in chart.palaces:
if p.is_afflicted():
print(p.name, "煞忌交冲")输出
疾厄 煞忌交冲load_plugin 只接受作用于 Astrolabe 的插件。要挂到别的类上,
像上例那样直接调用函数即可——插件机制本身没有魔法。