准备
正常情况下,创建class的实例后,可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。首先定义一个class
class A(object): pass
然后创建一个实例,并给实例添加属性和方法。
a = A() print a.__dict__ #{} A.name = 'xiaoming' #动态的给实例绑定属性,其实例属性会保存到实例的__dict__中 print a.__dict__ #{'name': 'xiaoming'} f = lambda :100 a.fun = f print a.__dict__ #{'fun': <function <lambda> at>, 'name': 'xiaoming'}
此时的name属性和fun()方法只有实例a能使用,类A的其他实例不能使用,如果想让类A的所有实例都能使用,我们需要给类A绑定方法
print A.__dict__ #... f = lambda :100 A.fun = f print A.__dict__ #... + 'fun': <function <lambda> at 0x0000000003582978>
此时,类A的所有实例就能使用方法fun()了。
"color: #ff0000">__slots__
"htmlcode">
class A(object): __slots__ = ('age','name') a = A() a.name = 'xiaoming' a.age = 10 a.id = 123456 #error AttributeError: 'A' object has no attribute 'id'
由于id不在__slots__中,所以实例不能添加id属性。任何试图给实例添加一个其名不在__slots__中的属性都将触发AttributeError异常。
实现原理
__slots__中的变量是类属性,类型为数据描述符。
#!/usr/bin/python # -*- coding: utf-8 -*- class Foo(object): __slots__ = ('age','name') def __init__(self,age = 0): self.age = age s = Foo.__dict__['age'] print s #<member 'age' of 'Foo' objects> print type(s) #<type 'member_descriptor'> '''证明为数据描述符''' print '__get__' in dir(s) #True print '__set__' in dir(s) #True
__slots__中的变量虽然是类属性,但是不同实例之间互不影响。因为描述符方法的一个参数为实例,建立一个实例和值的映射还是很简单的。如果不懂,建议看描述符 。
f1 = Foo(1) f2 = Foo(2) print f1.age,f2.age #1,2 print Foo.__dict__['age'].__get__(f1) #1 print Foo.__dict__['age'].__get__(f2) #2
__slots__的好处
如果类没有定义__slots__ ,该类的实例会有__dict__属性,通过__dict__可修改,删除,增加实例属性。
如果类定义了__slots__,该类的实例不会有__dict__属性。实例中的__dict__属性是非常耗内存的,当创建上百万个实例的时候,所有实例的__dict__会占用一块很大的内存。没有了__dict__的实例也就不能动态添加属性,只需分配固定的空间来存储已知的属性。因此使用__slots__的类能节省一部分内存开销。
对于不需要动态添加属性的类来说,应使用__slots__。
注意:不用过早的使用这个方法,它不利于代码维护,当实例很多(上千万)时,这种优化才有明显的效果。在实际使用中,__slots__从未被当作一种安全的特性来使用,它是对内存和执行速度的一种性能优化。使用__slots__的类的实例不再使用字典来存储实例属性,而是使用基于数组的一种更加紧凑的数据结构,所以当实例很多时,使用__slots__可以显著减少内存占用和执行时间。
class A(object): pass class B(object): __slots__ = ('age','name') a = A() b = B()
没有__slots__的类和实例
print a.__dict__ #{} print A.__dict__ ''' {'__dict__': <attribute '__dict__' of 'A' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} '''
有__slots__的类和实例
print b.__dict__ #AttributeError: 'B' object has no attribute '__dict__' print B.__dict__ ''' {'age': <member 'age' of 'B' objects>, '__module__': '__main__', '__doc__': None, '__slots__': ('age', 'name'), 'name': <member 'name' of 'B' objects>} '''
使用定义__slots__的类的注意事项
class Foo(object): __slots__ = ('age','name')
1.__slots__仅对当前类起作用,对子类是不起作用的,除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__。
class F1(Foo): pass class F2(Foo): __slots__ = () f1,f2 = F1(),F2() f1.a = 1 f2.a = 1 #AttributeError: 'F2' object has no attribute 'a' f2.age = 1
2.如果实例未给__slots__中的变量赋值,该实例不能使用__slots__中的变量。
f = Foo() print f.age #AttributeError: age f.age = 1 print f.age #1
3.实例将不再拥有__dict__,但是类还是拥有__dict__属性的,所以还是可以给类增加类属性的;
f = Foo() Foo.xx = 1 print f.xx #1
4.定义了__slots__后,如果__slots__中的变量为类变量,该变量对于该类的实例来说是只读的。如果想修改的话,可以通过类来修改。
class Foo(object): __slots__ = ('age','name') age = 10 def __init__(self): self.name = 'xiaoming' f = Foo() print f.name #'xiaoming' print f.age #10 f.name = 'xiaohong' #f.age = 12 #AttributeError: 'Foo' object attribute 'age' is read-only Foo.age = 12 #正确 print f.name #'xiaohong' print f.age #12 #del f.age #AttributeError: 'Foo' object attribute 'age' is read-only #del f.name 调用的是描述符方法__delete__,应该是将描述符中存储的实例与值的映射删除了 del f.name #实例属性的删除还是可以的,但是删除的并不是类字典中的name属性 print f.name #AttributeError: name del Foo.age #通过类来删除类属性还是可以的,不过这样会影响该类的所有实例 print f.age #AttributeError: 'Foo' object has no attribute 'age'
原因不知道…有知道的大神求指导…
参考网址
1.http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868200605560b1bd3c660bf494282ede59fee17e781000
2.http://www.jianshu.com/p/ef1797577f71
3.http://www.jianshu.com/p/82ce2151d73b
4.http://blog.csdn.net/lis_12/article/details/53453665
Python,__slots__
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]