-
__slots__
作用
- 类成员变量描述符
-
__slots__
是一个元祖 - 类的实例只能拥有
__slots__
中定义的变量 - 定义了
__slots__
之后就不再有__dict__
属性 - 在Python3中,类变量不能与
__slots__
预定义的变量名重名
- 示例1
class Foo(object):
__slots__ = ('x')
var = 9
def __init__(self):
self.a = 10
f = Foo()
运行时错误AttributeError: 'Foo' object has no attribute 'a'
。
原因:不能定义名称为a
的类实例变量
- 示例2
class Foo(object):
__slots__ = ('x')
var = 9
def __init__(self):
self.x = 10
f = Foo()
print(f.__dict__)
运行错误,拥有__slots__
的类不再有__dict__
属性。
- 示例3
class Foo(object):
__slots__ = ('x', 'y')
var = 9
def __init__(self):
self.x = 10
f = Foo()
# # 动态添加实例变量
f.y = 2
print('x= {}, y = {}'.format(f.x, f.y))
正确,动态添加的实例变量必须在__slots__
已经定义。
- 示例4
class Foo(object):
__slots__ = ('x')
var = 9
def __init__(self):
self.x = 10
f = Foo()
# # 动态添加实例变量
f.y= 2
print('x= {}, y = {}'.format(f.x, f.y))
运行错误:AttributeError: 'Foo' object has no attribute 'y'
。
原因: 动态添加的属性必须在__slots__
中已经定义
- 示例5
class Foo(object):
__slots__ = ('x')
x = 9
def __init__(self):
pass
f = Foo()
print('Foo.x: {}'.format(Foo.x))
print('f.x: {}'.format(f.x))
f.x = 99
print('f.x: {}'.format(f.x))
运行错误:alueError: 'x' in __slots__ conflicts with class variable
。
特别需要注意的是在Python2中,当类变量与__slots__
预定义的变量名冲突时,冲突的变量变为只读。
- 示例6
普通类与__slots__
类的dir
命令区别。
class Foo(object):
__slots__ = ('x', 'y')
def __init__(self):
pass
f = Foo()
class Goo(object):
def __init__(self):
self.x = 1
self.y = 2
g = Goo()
print(dir(Foo))
print(dir(Goo))
print(dir(f))
print(dir(g))
结果:
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', **'__slots__'**, '__str__',
'__subclasshook__', 'x', 'y']
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__']
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__','__setattr__', '__sizeof__', '__slots__', '__str__',
'__subclasshook__', 'x', 'y']
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'x', 'y']
一个包含的是__slots__
,x
和 y
,普通类肯定包含__dict__
。
网友评论