1.当创建大量实例时如何节省内存
对于那些主要用作简单数据结构的类,通常可以在类定义中增减__slot__属性,以此来减少对内存的使用
class Date():
__slots__ = ['year', 'month', 'day']
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
当定义了__slots__属性的时候,python就会针对实例采用一种更加紧凑的内部表示,不再让每一个实例都创建一个__dict__字典,现在的实例是围绕着一个固定长度的小型数组来创建的,这和一个元组或者列表很相似。
注意:
- 使用__slots__之后我们将没办法再对实例添加任何新的属性——我们被限制只允许使用__slots__中列出的那些个属性名。
- 定义了__slots__的类不支持某些特定的功能,比如多继承。
就大部分而言,我们应该只针对那些在程序中被当做数据结构而频繁使用的类采用__slots__技法,所以一般不建议使用。
如下例:
class Date():
__slots__ = ['year', 'month', 'day']
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
d = Date('2017','09','08')
d.__setattr__('ha','hi')
print(d.ha)
Traceback (most recent call last):
File "D:/github/pycharmDevelopment/numpyy.py", line 35, in <module>
d.__setattr__('ha','hi')
AttributeError: 'Date' object has no attribute 'ha'
但是当我们将__slots__ = [‘year’, ‘month’, ‘day’]这一行注释掉之后就不会有错误,输出结果为hi,由此可见__slots__阻止了示例的属性添加
2. 将名称封装到类中
在python中我们习惯使用特定的命名规则来表达对数据和方法的用途。
第一个规则是任何以单下划线(_)开头的名字应该总是被认为只属于内部实现。
Python不会阻止其他人访问内部名称,但是如果有人这么做了,那么被认为是粗鲁的,并且会导致代码的脆弱不堪。
class Animal():
def __init__(self,kind):
self.kind = kind
self.__private = 0
self._inter = 1
def __private_method(self):
print('Animal')
class Bird(Animal):
def __init__(self,kind):
super().__init__(kind)
self.__private = 2
self._inter = 3
def __private_method(self):
print('Bird')
bird=Bird('bird')
print(bird._inter)#结果是3
以双下划线打头的名称会导致出现名称的重整行为,以上面的例子来说,私有属性会分别被重命名为_B__private和_B__private_method。对于名称重整我们必须要知道的是:私有属性和方法是不能通过继承而被覆盖的。
bird=Bird('bird')
print(bird._Animal__private)
bird._Animal__private_method()
print(bird._Bird__private)
bird._Bird__private_method()
输出结果为:
0
Animal
1
bird
可见私有属性和方法都没有被覆盖掉
对于单或者双下划綫名称,我们应该尽量让非公有名称以单下划线开头,对于代码中会涉及子类话处理而且有些内部属性应该对子类进行隐藏,那么此时就应该使用双下划线了。