V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
mengzhuo
V2EX  ›  Python

尽信书不如无书,从一道 Python 单例面试题想到的

  •  
  •   mengzhuo · 2015-06-08 14:58:26 +08:00 · 4445 次点击
    这是一个创建于 3490 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近在网上看到一道基本面试题:
    Python单例如何实现?

    所谓的标准答案里,有用元编程(metaclass)的,有用decorator cache的
    但我觉得这些都不如module cache来得快,也不如module cache简单优雅,上面的方法都是故作玄虚。
    下面就有说效率比module cache来得快!
    我现在就告诉大家,那些网上的,所谓的标准答案至少慢100%,压根不如最简单的方法,证据在此,
    第 1 条附言  ·  2015-06-08 17:33:01 +08:00
    15 条回复    2015-08-06 11:04:51 +08:00
    wohenyingyu01
        1
    wohenyingyu01  
       2015-06-08 15:19:29 +08:00
    下面呢?
    nooper
        2
    nooper  
       2015-06-08 15:24:32 +08:00
    单例模式在多进程下呢?
    est
        3
    est  
       2015-06-08 15:32:12 +08:00
    m = ModuleSingleton()


    这货不就是全局变量?

    多进程考虑单例模式,直接反问主考官星际网络30%掉包 1500ms 延迟下集群如何实现单例。
    mengzhuo
        4
    mengzhuo  
    OP
       2015-06-08 15:52:46 +08:00
    @est

    如果你在其他模块里import进来就不是了

    只是为了说明metaclass decorator cache都是不必要的花式动作
    ibigbug
        5
    ibigbug  
       2015-06-08 16:34:42 +08:00
    ModuleSingleton 跟其他两个不一样吧。这个是事先生成好了一个放在那里等人来用。
    binux
        6
    binux  
       2015-06-08 16:44:46 +08:00   ❤️ 1
    第一次听说创建个全局变量就叫单例的。
    如果这个单例我实际上不用呢?你也要创建吗?
    Smartype
        7
    Smartype  
       2015-06-08 17:19:30 +08:00 via iPhone
    1. 这就是 singleton???
    2. 这样就快?
    哪位给解释下
    mengzhuo
        8
    mengzhuo  
    OP
       2015-06-08 17:30:13 +08:00
    @binux
    @Smartype
    你们都不看下面那个gist是怎么用的么!!创建的是module级的对象!!
    真要深追的话,哪个单例不是跟着对象的“全局变量”?

    快100%不算快么
    hahastudio
        9
    hahastudio  
       2015-06-08 17:36:45 +08:00
    全局变量就算单例我也就不提了,用 Module 算是一个讨巧的方法
    但是你只能庆幸你的 Python 实现是带 GIL 的,如果是不带 GIL 的= =
    dddd
        10
    dddd  
       2015-06-08 17:38:54 +08:00   ❤️ 1
    这是我们 Java 设计模式课上老师所讲的翻版: http://damnever.github.io/2015/04/07/singleton-pattern-in-python/
    JQ
        11
    JQ  
       2015-06-08 17:51:00 +08:00
    以前都没有关注到这个
    Smartype
        12
    Smartype  
       2015-06-08 20:19:28 +08:00
    @dddd @hahastudio 对啊,double check才对嘛,我觉得楼主不知道我要说什么,好在python有GIL,也是可以的,哈哈
    ming2281
        13
    ming2281  
       2015-06-08 20:33:12 +08:00
    缓存一个URL在模块级别,题主是这样写的吗?

    ```
    _URL = xxx
    def get(refresh=False):
    if refresh:
    get.reates = {}
    if get.retes:
    return get.rates

    with urllib.request.urlopen(_URL) as f:
    for line in f:
    line = line.rstrip().decode('utf-8')
    if not line or line.startswith(("#", "Date")):
    continue
    name, currency,*rest = re.split(r"\s*,\s*, line)
    key = "{}{})".format(name, currency)
    try:
    get.rates[key] = float(rest[-1])
    except ValueError as err:
    print "error:{}: {}".format(err, line)
    return get.rates
    get.rates = {}
    ```
    est
        14
    est  
       2015-06-09 12:24:30 +08:00
    还是ruby简单。直接 ||= 就行了。
    aec4d
        15
    aec4d  
       2015-08-06 11:04:51 +08:00
    题主啊,你应该先别谈效率。。。先写对了再说。。。
    你这里至少要加一个@classmethod 这样就是一个正确的单例了。再根据6楼说的在调用的时候在创建。那么可以考虑这样写
    class ModuleSingleton(object):

    @classmethod
    def get(cls):
    if not hasattr(cls, '_instance'):
    cls._instance = 0
    cls._instance += 1
    return cls._instance


    a = ModuleSingleton()
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   942 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:57 · PVG 05:57 · LAX 13:57 · JFK 16:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.