酷爱听戏曲 發表於 2026-3-5 09:03:00

在Python中用any-singleton实现单例模式

<h1 id="单例模式">单例模式</h1>
<p>“单例”即在全局有且只有一个的实例,差不就类似于“全局变量”。</p>
<p>我个人常用类似以下的代码来实现单例模式:</p>
<pre><code class="language-python">GLOBAL_KEY = '_my_coffee'
if GLOBAL_KEY not in globals():
    # 初始化:
    globals() = {
      'cup_of': 'tea'
    }
coff = globals()

print(coff['cup_of'])# Output: tea
</code></pre>
<p>上面的<code>coff</code>就是一个单例,全局仅会初始化一次,并总是同一个对象。</p>
<p><em>至于其他的实现方法,这里不多做赘述。大家可以去看看站内的:Python中的单例模式的几种实现方式的及优化</em></p>
<h1 id="any-singleton">Any-singleton</h1>
<p>大部分情况下,单例模式可以很容易得被实现,并且正确运行。但总是要写一小段代码来实现,就不那么方便,也不易于管理。<br>
为此,我就做了个简易的单例模式工具库——<code>Any-singleton</code>。</p>
<p><code>Any-singleton</code>提供了两大功能:“创建单例”和“使函数仅运行一次”。</p>
<h2 id="创建单例">创建单例</h2>
<p>我们仅需要调用<code>singleton()</code>并传入一个“唯一域名”和一个用于初始化的值,就可以很快的创建一个单例对象:</p>
<pre><code class="language-python">from any_singleton import singleton

tea = singleton('my_project.main.coffee', 'tea')
</code></pre>
<br>
<p>当然,也可以不直接给一个值,而是利用<code>singleton()</code>实例化一个对象作为单例的初始值:</p>
<pre><code class="language-python">from any_singleton import singleton

my_range = singleton('my_project.main.coffee', range, 123)
</code></pre>
<p>当第二个参数为一个<code>type</code>时,<code>singleton()</code>不会把该参数直接作为初始值,而是将其结合后面的参数实例化再作为初始值。<br>
该单例的实例化过程在整个程序的生命周期将只会执行一次。<br>
<br></p>
<p>为了消除歧义,你还可以使用<code>singleton_value()</code>来替代<code>singleton()</code>,使之无论第二个参数是不是<code>type</code>类型的,都直接将其直接作为初始值使用:</p>
<pre><code class="language-python">from any_singleton import singleton_value

class Tea:
    pass

tea = singleton_value('my_project.main.coffee', type(Tea))
</code></pre>
<h2 id="使函数仅运行一次">使函数仅运行一次</h2>
<p>使用<code>@once()</code>装饰器来创建一个在整个程序生命周期里只会被调用一次的函数:</p>
<pre><code class="language-python">import tomllib
from any_singleton import once, singleton

@once('my_project.initializations.init')
def init(config_path: str) -&gt; None:
    with open(config_path, 'rb') as f:
      config = singleton('my_project.globals.config', tomllib.load(f))

init('config.toml')
</code></pre>
<br>
<p>或者使用<code>@run_once()</code>装饰器来创建一个被<code>@once()</code>装饰的函数,并立即自动调用一次。</p>
<pre><code class="language-python">import tomllib
from any_singleton import run_once, singleton

@run_once(
    'my_project.initializations.init',
    second_calling = SecondCallingBehaviour.NoneToReturn,
    # 以下的参数将传递给被装饰的`init()`。
    'config.toml'
)
def init(config_path: str) -&gt; None:
    with open(config_path, 'rb') as f:
      config = singleton('my_project.globals.config', tomllib.load(f))
</code></pre>
<hr>
<p>基本的用法就是这些了。</p>
<p>更多内容可以去查看我已经在PyPI上发布的any-singleton。</p>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:Orange233,转载请注明原文链接:https://www.cnblogs.com/orange233/p/19670921/using_any-singleton_to_implement_singleton_pattern</p><br><br>
来源:https://www.cnblogs.com/orange233/p/19670921/using_any-singleton_to_implement_singleton_pattern
頁: [1]
查看完整版本: 在Python中用any-singleton实现单例模式