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

2015-06-08 14:58:26 +08:00
 mengzhuo
最近在网上看到一道基本面试题:
Python单例如何实现?

所谓的标准答案里,有用元编程(metaclass)的,有用decorator cache的
但我觉得这些都不如module cache来得快,也不如module cache简单优雅,上面的方法都是故作玄虚。
下面就有说效率比module cache来得快!
我现在就告诉大家,那些网上的,所谓的标准答案至少慢100%,压根不如最简单的方法,证据在此,
https://gist.github.com/mengzhuo/2fbaff790e6e9d786f34
4442 次点击
所在节点    Python
15 条回复
wohenyingyu01
2015-06-08 15:19:29 +08:00
下面呢?
nooper
2015-06-08 15:24:32 +08:00
单例模式在多进程下呢?
est
2015-06-08 15:32:12 +08:00
m = ModuleSingleton()


这货不就是全局变量?

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

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

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

快100%不算快么
hahastudio
2015-06-08 17:36:45 +08:00
全局变量就算单例我也就不提了,用 Module 算是一个讨巧的方法
但是你只能庆幸你的 Python 实现是带 GIL 的,如果是不带 GIL 的= =
dddd
2015-06-08 17:38:54 +08:00
这是我们 Java 设计模式课上老师所讲的翻版: http://damnever.github.io/2015/04/07/singleton-pattern-in-python/
JQ
2015-06-08 17:51:00 +08:00
以前都没有关注到这个
Smartype
2015-06-08 20:19:28 +08:00
@dddd @hahastudio 对啊,double check才对嘛,我觉得楼主不知道我要说什么,好在python有GIL,也是可以的,哈哈
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
2015-06-09 12:24:30 +08:00
还是ruby简单。直接 ||= 就行了。
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()

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/196927

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX