让对象回答一切。

输入任意属性与调用链。UniversalObject 不拒绝,不终止,只把自己交还给下一步。

拆开四种巧思
UniversalObject playgroundidentity: 0x7F21
u.
可输入属性、方法和参数,按 Enter 执行。
result is u → True
每一次 __getattribute__ 与 __call__ 都返回同一对象。

四个技巧,都在重新安排控制权。

黑洞对象

访问任意属性、以任意参数调用,结果仍是自身。它适合测试替身,也能作为不需要空判断的空对象。

def __getattribute__(self, name): return self
def __call__(self, *args, **kwargs): return self

记住结果

lru_cache 把纯函数的参数与结果放进缓存。fib(6) 的子问题只计算一次,之后直接命中。

@lru_cache(maxsize=128)
def fib(n): return n if n < 2 else fib(n-1) + fib(n-2)

类型决定路线

singledispatch 根据第一个参数类型选择实现。新模块可注册新类型,不必修改原函数。

@to_str.register
def _(x: list): return "list:" + ",".join(map(str, x))

把执行变成数据

服务端用 GLOBALS、COLLECTION 与 FUNCTION 描述操作,通过 RPC 传输,客户端再还原为真实的 UI 调用、属性写入和计时器。

GLOBALS()["clientApi"].RegisterUI(...) → clientApi.RegisterUI(...)

Complete article

完整原文

文字、链接、图片、表格与代码均保留 开始阅读

UniversalObject 万用对象

PYTHON
class UniversalObject(object):
    """ 万用对象 """
    def __init__(self):
        pass

    def __getattribute__(self, __name):
        return self

    def __call__(self, *args, **kwds):
        return self

行为示例

PYTHON
u = UniversalObject()
result = u.any.attr.or_method(1, x=2).more.calls
print(result is u)  # True

典型用途

functools.lru_cache 结果缓存

PYTHON
from functools import lru_cache

@lru_cache(maxsize=128)
def fib(n: int) -> int:
    return n if n < 2 else fib(n - 1) + fib(n - 2)

print(fib(6))

上述 lru_cache 代码的工作过程如下:

  1. 当你第一次调用 fib(n) 时,函数会正常递归计算斐波那契数列,并把每个参数和结果存入缓存。
  2. 如果后续再次调用 fib(n),且参数 n 之前已经算过,直接从缓存返回结果,不再递归计算。
  3. maxsize=128 表示最多缓存 128 个不同参数的结果。

例如,fib(6) 实际只会递归计算一次,后续再调用 fib(6) 或更小的参数时,都会直接命中缓存,速度极快。

functools.singledispatch 单分派泛函数

PYTHON
from functools import singledispatch

@singledispatch
def to_str(x) -> str:
    return f"obj:{x!r}"

@to_str.register
def _(x: int) -> str:
    return f"int:{x}"

@to_str.register
def _(x: list) -> str:
    return "list:" + ",".join(map(str, x))

print(to_str(42))       # int:42
print(to_str([1,2,3]))  # list:1,2,3

globals() C/S架构RPC传输

期望效果

服务端RPC传递以下代码

PYTHON
ServerSystems.ClientRpc.RequestToClient(convert_operation(COLLECTION(
    GLOBALS()["clientApi"].SetHudChatStackVisible(False),
    GLOBALS()["clientApi"].RegisterUIAnimations(CommonUI.DEFINITION, True),
    GLOBALS()["clientApi"].RegisterUI(CommonUI.NAMESPACE, CommonUI.KEY, GLOBALS()["custom_ui_class_path"], CommonUI.SCREEN_DEF),
    GLOBALS().setitem(CommonUI.SCREEN_DEF, GLOBALS()["clientApi"].CreateUI(CommonUI.NAMESPACE, CommonUI.KEY, {"isHud": 1})),
    GLOBALS()[CommonUI.SCREEN_DEF].setattr("GameComponent", GLOBALS()["clientApi"].GetEngineCompFactory().CreateGame(LevelId)),
    GLOBALS()[CommonUI.SCREEN_DEF].setattr("AddChatMessage", FUNCTION(COLLECTION(
        GLOBALS()[CommonUI.SCREEN_DEF].Clone("/templates/chat_item", "/chat_messages", LOCALS()["args"][0]),
        GLOBALS()[CommonUI.SCREEN_DEF].GetBaseUIControl("/chat_messages/" + LOCALS()["args"][0] + "/anchor/content").asLabel().SetText(LOCALS()["args"][1]),
        GLOBALS()[CommonUI.SCREEN_DEF].GameComponent.AddTimer(LOCALS()["args"][2], GLOBALS()[CommonUI.SCREEN_DEF].RemoveComponent, "/chat_messages/" + LOCALS()["args"][0], "/chat_messages")
    ))),
    GLOBALS()[CommonUI.SCREEN_DEF].setattr("AddDeathMessage", FUNCTION(COLLECTION(
        GLOBALS()[CommonUI.SCREEN_DEF].Clone("/templates/death_item", "/death_messages", LOCALS()["args"][0]),
        GLOBALS()[CommonUI.SCREEN_DEF].GetBaseUIControl("/death_messages/" + LOCALS()["args"][0] + "/anchor/content").asLabel().SetText(LOCALS()["args"][1]),
        GLOBALS()[CommonUI.SCREEN_DEF].GetBaseUIControl("/death_messages/" + LOCALS()["args"][0] + "/anchor/outline").SetVisible(LOCALS()["args"][2]),
        GLOBALS()[CommonUI.SCREEN_DEF].GameComponent.AddTimer(LOCALS()["args"][3], GLOBALS()[CommonUI.SCREEN_DEF].RemoveComponent,"/death_messages/" + LOCALS()["args"][0], "/death_messages")
    )))
)), target)

对应的客户端等价运行如下代码

PYTHON
clientApi.SetHudChatStackVisible(False)
clientApi.RegisterUIAnimations(CommonUI.DEFINITION, True)
clientApi.RegisterUI(CommonUI.NAMESPACE, CommonUI.KEY, GLOBALS()["custom_ui_class_path"], CommonUI.SCREEN_DEF)
CommonUI.SCREEN_DEF = clientApi.CreateUI(CommonUI.NAMESPACE, CommonUI.KEY, {"isHud": 1})
CommonUI.SCREEN_DEF.GameComponent = clientApi.GetEngineCompFactory().CreateGame(LevelId)

def AddChatMessage(id_, text, ttl):
    path = "/chat_messages/" + str(id_)
    CommonUI.SCREEN_DEF.Clone("/templates/chat_item", "/chat_messages", id_)
    CommonUI.SCREEN_DEF.GetBaseUIControl(path + "/anchor/content").asLabel().SetText(text)
    CommonUI.SCREEN_DEF.GameComponent.AddTimer(ttl, CommonUI.SCREEN_DEF.RemoveComponent, path, "/chat_messages")

def AddDeathMessage(id_, text, outlined, ttl):
    path = "/death_messages/" + str(id_)
    CommonUI.SCREEN_DEF.Clone("/templates/death_item", "/death_messages", id_)
    CommonUI.SCREEN_DEF.GetBaseUIControl(path + "/anchor/content").asLabel().SetText(text)
    CommonUI.SCREEN_DEF.GetBaseUIControl(path + "/anchor/outline").SetVisible(outlined)
    CommonUI.SCREEN_DEF.GameComponent.AddTimer(ttl, CommonUI.SCREEN_DEF.RemoveComponent, path, "/death_messages")

CommonUI.SCREEN_DEF.AddChatMessage = AddChatMessage
CommonUI.SCREEN_DEF.AddDeathMessage = AddDeathMessage
🐍 tech

Python 笔记
一些冷门但高效的设计巧思

一些冷门但高效的设计巧思

2025年9月3日 4 tricks Python
01

UniversalObject 万用对象

Black Hole Object Pattern

一个"万用/黑洞对象"。访问任意属性、调用任意方法、以任意参数调用,都不会报错,并且始终返回自身。可无限链式调用,结果始终是原对象。

Magic Method
__getattribute__

拦截所有属性访问,返回 self

Magic Method
__call__

拦截函数调用,返回 self

universal_object.py
class UniversalObject(object):
    """万用对象"""
    def __init__(self):
        pass

    def __getattribute__(self, __name):
        return self

    def __call__(self, *args, **kwds):
        return self
demo.py
u = UniversalObject()
result = u.any.attr.or_method(1, x=2).more.calls
print(result is u)  # True
🧪 Mock / Test Doubles ⚙️ Config Placeholders 🔗 Fluent API Stubs 🛡️ Null Object Pattern
02

functools.lru_cache

Memoization with Zero Boilerplate

为纯函数结果做缓存,避免重复计算。maxsize 控制缓存大小,typed=True 区分不同类型的同值参数。一行装饰器,性能飞升。

fibonacci.py
from functools import lru_cache

@lru_cache(maxsize=128)
def fib(n: int) -> int:
    return n if n < 2 else fib(n - 1) + fib(n - 2)

print(fib(6))  # 8
1 首次调用 fib(n) 时正常递归计算,并将参数与结果存入缓存
2 后续调用相同参数时直接返回缓存结果,跳过递归
3 maxsize=128 限制最多缓存 128 个不同参数的结果,LRU 策略淘汰

fib(6) 实际只递归计算一次。后续所有调用直接命中缓存,时间复杂度从 O(2^n) 降至 O(n)。

03

functools.singledispatch

Type-Based Function Overloading

基于"第一个参数类型"分派到对应实现。可在任意模块延后注册新类型的处理逻辑,无需修改原函数。Python 版的函数重载。

dispatch.py
from functools import singledispatch

@singledispatch
def to_str(x) -> str:
    return f"obj:{x!r}"

@to_str.register
def _(x: int) -> str:
    return f"int:{x}"

@to_str.register
def _(x: list) -> str:
    return "list:" + ",".join(map(str, x))
Default
to_str(x)

未注册类型走 fallback

Registered
@to_str.register

按类型注解自动分派

if isinstance(x, int) 链更清晰、更可扩展。第三方库可在不动原函数的前提下注册新类型。

04

globals() C/S RPC

Serialize Execution as Data

利用 globals() 将代码操作序列化为可传输的数据结构,通过 RPC 发送到客户端执行。服务端描述"做什么",客户端还原为真实调用。

rpc_pattern.py
# Server-side: serialize operations as data
ServerSystems.ClientRpc.RequestToClient(
    convert_operation(COLLECTION(
        GLOBALS()["clientApi"].SetHudChatStackVisible(False),
        GLOBALS()["clientApi"].RegisterUI(...),
        GLOBALS().setitem(key, value),
    )), target
)

# Client-side equivalent execution:
clientApi.SetHudChatStackVisible(False)
clientApi.RegisterUI(...)
globals()[key] = value
Server Side
GLOBALS()["key"]

引用客户端全局变量

Client Side
globals()[key]

还原为真实属性访问

🎮 Game UI RPC 🌐 Remote Execution 📦 Operation Batching

UniversalObject 的链式调用记录下来,序列化后通过网络传输,在远程端还原执行。这是四个技巧的完美结合。