V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  aijam  ›  全部回复第 13 页 / 共 19 页
回复总数  378
1 ... 5  6  7  8  9  10  11  12  13  14 ... 19  
2019-01-19 10:31:15 +08:00
回复了 whoami9894 创建的主题 Python 为什么要在__slots__中添加__dict__属性?
TLDR:
使用__slots__是为了节约内存使用,但是带来的两个副作用:
1. 没了__dict__,无法动态加属性。
2. 没了__weakref__,无法使用弱引用。
为了克服这两个副作用需要把它们重新加回去。

=================================================
1. 普通的 class 会在 instance 初始化的时候把 attribute 放到__dict__里,也就是说内部维护了一个多余的 dict。
>>> class A():
... def __init__(self):
... self.x = 1
... self.y = 2
...
>>> a = A()
>>> a.__dict__
{'x': 1, 'y': 2}

2. 为了避免在__dict__里浪费内存,有了__slots__。
>>> class B():
... __slots__ = ('x', 'y')
... def __init__(self):
... self.x = 1
... self.y = 2
...
>>> b = B()
>>> b.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'B' object has no attribute '__dict__'
可以看出__dict__消失了。

3. __dict__的存在目的是为了能在 instance 里动态加入新的属性,新的属性会加到__dict__里。
>>> a.z = 3
>>> a.__dict__
{'x': 1, 'y': 2, 'z': 3}

但用了__slots__后就无法动态加属性了。
>>> b.z = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'B' object has no attribute 'z'

4. 为了依然能动态加属性,我们在__slots__里重新加入__dict__。
>>> class C():
... __slots__ = ('x', 'y', '__dict__')
... def __init__(self):
... self.x = 1
... self.y = 2
...
>>> c = C()
>>> c.__dict__
{}
我们注意到,初始化时__dict__初始是空的,依然比 a 要节约内存。
这时候动态加属性也没问题了。
>>> c.z = 3
>>> c.__dict__
{'z': 3}

5. 具体验证下__slots__到底做了什么。
>>> set(dir(b)) - set(dir(a))
{'__slots__'}
>>> set(dir(a)) - set(dir(b))
{'__dict__', '__weakref__'}
可以看出 b 加了__slots__后,相较 a 少了__dict__以及__weakref__。
同理,为了使用弱引用,需要把__weakref__加回去。

但有一点我还存有疑问:当初设计__slots__时为什么要去掉__weakref__?
2019-01-19 06:01:29 +08:00
回复了 Ewig 创建的主题 Python Python numpy 如何看几维?
这个很简单啊
2019-01-19 05:49:00 +08:00
回复了 victor97 创建的主题 程序员 什么是真正的程序员
虽然每种人写的挺形象,但结论一句“解决真正需要的问题”和小王子一样的理想主义鸡汤,伟光正但无用。而其实文中出现的每种人你都能找到自己的影子,只是在不同的场合或者在不同人眼里。
2019-01-17 06:26:10 +08:00
回复了 eagleweb 创建的主题 问与答 学习编程,先学习函数后学习变量顺序是否正确?
@secondwtq 对的,学 lambda calculus 就不用纠结 lz 的问题了。
2019-01-16 06:14:13 +08:00
回复了 ghostheaven 创建的主题 问与答 8 台 2 核跟 2 台 8 核做 web 后端
8 台 2 核。有利于部署维护和容灾,后端服务总有某台服务器下线(部署、维护或宕机)的时候。如果一共两台机器,平时每台机跑了 50%CPU,其中一台下线时另一台就会飙到 100%,很容易影响服务的 latency 和 availability。8 台机器的话少一台也只是少了 1/8 的 capacity。
2019-01-16 02:04:47 +08:00
回复了 chocolatesir 创建的主题 问与答 阅读障碍有什么有效的训练方法吗?好痛苦啊
你们确定你们的回复 lz 看得懂?
2019-01-12 20:01:30 +08:00
回复了 c3yangliu 创建的主题 Python 怎么自己实现 if?
@zhustec 不用 python 也是玩自己呀。
2019-01-12 19:42:50 +08:00
回复了 c3yangliu 创建的主题 Python 怎么自己实现 if?
@laziji 诶,这也是一种办法
>>> def _if(predict, b1, b2):
... d = {True: b1, False: b2}
... return d[predict]()
...
>>> _if(True, lambda: print(1), lambda: print(2))
1
>>> _if(False, lambda: print(1), lambda: print(2))
2
2019-01-12 19:35:39 +08:00
回复了 c3yangliu 创建的主题 Python 怎么自己实现 if?
这是你想要的吗?
>>> def _if(predict, b1, b2):
... predict and b1()
... predict or b2()
...
>>> _if(True, lambda: print(1), lambda: print(2))
1
>>> _if(False, lambda: print(1), lambda: print(2))
2

还是想玩 lambda calculus ?
>>> _True = lambda x, y: x
>>> _False = lambda x, y: y
>>> def _if(predict, b1, b2):
... predict(b1, b2)()
...
>>> _if(_True, lambda: print(1), lambda: print(2))
1
>>> _if(_False, lambda: print(1), lambda: print(2))
2
2019-01-12 17:27:58 +08:00
回复了 chinesehuazhou 创建的主题 Python 聊聊技术写作的个人体会(内有公众号宣传,不喜勿进)
目测 lz 理解有点偏啊。
1. 生拉硬套把 magic method 和是否是 builtin_function_or_method 联系起来,问题是他们虽然使用上有一点关系但没必然关联啊。
2. 逻辑不通,明明说了“使用 type() 进行判断,结果为 builtin_function_or_method 的才是内置函数”,后面得出的结论是要“以上两种方法得要结合起来看”。没看出 type()有什么地方不够用的啊。
3. 如果 lz 纠结是 range 是不是 builtin_function_or_method,那这是一个 trivial 的问题,调用 type 即可。如果 lz 纠结的是 range 到底是 function 还是 type,python 里面 function 本身是一个非常非常宽泛概念,比如 lambda/callable/generator function/classmethod/instancemethod/staticmethod 你怎么界定他们是不是 function。用 Python 的人更多的是问是否是 callable 这个比较实际的问题,比如有 callable(...)和 typing.Callable 却没有 isfunction(...)和 typing.Function。
4. str/list/range 即是 type 也是 constructor。constructor 是特殊的 function,用来构造 type 的 instance,那说 range 是 function 也不是不可。比如 str(123)里它就是 constructor,isinstance('123', str)里它就是 type。如果你了解一点 Haskell 里 type constructor 和 data constructor 的差别,这点道理就比较好理解。
不客气的说:lz 发现了 range type 的存在,然后通过自己的联想给了一个蹩脚的解释。
2019-01-11 03:13:30 +08:00
回复了 leleron 创建的主题 电影 狗十三
六爷也说空空不能和晶晶谈恋爱,我当然是支持每个人对电影有不同理解和评价的。
2019-01-10 14:13:03 +08:00
回复了 cwx391497 创建的主题 C C 语言中结构体相互嵌套有什么优点吗
爹认识儿子,儿子也要认识爹。
2019-01-09 01:31:37 +08:00
回复了 allenhu 创建的主题 全球工单系统 Macbook pro 的质量实在堪忧,购买前三思!
mba 2012 11inch, 2015 11 inch/13 inch 三台至今服役,2012 那台免费召回过一次 ssd。
公司的 mbp 2015 屏幕前不久突然之间屏幕坏了。
个人感觉也是品控 mba>mbp。
2019-01-06 16:32:58 +08:00
回复了 dengtongcai 创建的主题 程序员 shell 关于字符串切割成数组的问题
str 是"1 2 3",字符串
arr 是(1 2 3),数组
再举个例子:
> str="1 2 3"; arr=(0 $str 4)
> echo ${arr[*]}
0 1 2 3 4
2019-01-06 15:47:28 +08:00
回复了 dengtongcai 创建的主题 程序员 shell 关于字符串切割成数组的问题
> str="abc"; echo ${#str[@]}
1
> str="abc"; echo ${#str}
3
@chinesehuazhou 较真的说,本主题和 mutability 关系不大。
@laike9m 的说法混淆了 stateful 和 mutability 的侧重点,说 iterator 是 stateful 更适合。
同样作为 Iterable,list/dict/set 是 mutable 的,而 range/tuple/fronzenset 是 immutable 的。
是否是 Iterable 只和他们能不能被“逐一”读取有关,和它们能否被修改无关。
Iterator 的出现原本是为了解决无 index 的 Iterable 如何逐一读取的问题,比如 list 你能用 index 读取元素但 set 就不行。造成的结果是,相比通过递增 index 来逐一读取,用了 iterator 反而是让修改容器变得更困难(更 immutable 了)。
这和“不用 iterator 是由于 range 必须 immutable ”这种说法逻辑上是矛盾的。
感觉没抓住重点,其实就是 Iterable 和 Iterator 的区别。
通俗地说,
- 能把里面的内容“逐一”取的容器是 Iterable,比如 list、string、dict 等。range 属于这一类。
- 为了将 Iterable 容器里的内容“逐一”取出来,我们需要通过 Iterator (即迭代器)。通过 iter()我们可以获得一个 Iterable 对应的 Iterator。
比如,
[1,2,3]是 list,所以是 Iterable,但它本身不是 Iterator。iter([1,2,3])才是它对应的 Iterator。
同理,range(10)也是 Iterable 而不是 Iterator。iter(range(10))才是它对应的 Iterator。
在实际代码中,
Iterator 最大的特点是“一次性”,用完了就不能用第二次。
比如,range 对象是可以多次用的。
r = range(5)
for i in r: print(i) # print 0 to 4
for i in r: print(i) # print 0 to 4
而如果返回的是 Iterator,你就只能用一次。
it = iter(range(5))
for i in it: print(i) # print 0 to 4
for i in it: print(i) # print nothing
range 范围作为一个“实体”概念,设计成可复用的 Iterable 更合理,这和 map/filter/zip 这些作为一次性“操作”存在的概念略有不同。当然这一定程度上也有 py2 的历史原因,过去无论 range/map/sorted 都统一返回 list,为了性能优化 py3 才分别返回 Iterable, Iterator 和 list。
2019-01-05 11:39:10 +08:00
回复了 jssyxzy 创建的主题 程序员 macbook 外接屏幕有什么好的方法?
应该是你的 macbook 电用完了。
2019-01-03 10:20:15 +08:00
回复了 talentl 创建的主题 Python 请问如何用 Python 实现如下计算功能
sum(2**x for x in range(1,6))
1 ... 5  6  7  8  9  10  11  12  13  14 ... 19  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   980 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 32ms · UTC 18:59 · PVG 02:59 · LAX 10:59 · JFK 13:59
Developed with CodeLauncher
♥ Do have faith in what you're doing.