数据和自省
私有属性
类型里面定义的变量叫类属性,类属性分为两种:公有属性和私有属性
私有属性:由单下划线或双下划线开头的属性名称,叫做私有属性;
公有属性可以在类外面通过类或者类创建的实例直接调用;
由单下划线开头的私有属性也可以在类外面通过类或者类创建的实例直接调用,
但是由双下划线开头的私有属性不可以在类外面通过类或者类创建的实例直接调用,因为它被改了名字,
改成了:_类名双下划线开头的私有属性名,如果想要调用,则要用新名字;
私有属性可被继承;
class MyAttr(object): attr = 100 _attr = 666 # 由单下划线开头的属性名,在外部可以直接访问 __attr = 999 # 由双下划线开头的属性名,在外部不能直接访问,被改名字了,改成_MyAttr__attr ma = MyAttr() print(ma._attr) print(ma._MyAttr__attr) 执行结果为: 666 999
Python并没有真正的私有化支持,但可用下划线得到伪私有,Python中默认遵循的习惯是,只要带下划线开头的函数,方法或是数据成员,都被看成私有;
__dict__属性和__slots__方法
__dict__属性可以查看类所有的属性和方法;
class MyAttr(object): attr = 100 _attr = 666 # 由单下划线开头的属性名,在外部可以直接访问 __attr = 999 # 由双下划线开头的属性名,在外部不能直接访问,被改名字了,改成_MyAttr__attr ma = MyAttr() print(ma._attr) print(ma._MyAttr__attr) print(MyAttr.__dict__) # 查看该类的所有属性和方法 class MyAttrSon(MyAttr): name = "yeweiyin" _name = "lzh" print(MyAttrSon.__dict__) 执行结果为: {'__module__': '__main__', 'attr': 100, '_attr': 666, '_MyAttr__attr': 999, '__dict__': <attribute '__dict__' of 'MyAttr' objects>, '__weakref__': <attribute '__weakref__' of 'MyAttr' objects>, '__doc__': None} {'__module__': '__main__', 'name': 'yeweiyin', '_name': 'lzh', '__doc__': None}
由上面的例子可以看到,通过继承的子类,其内部的属性没有
'__dict__': <attribute '__dict__' of 'MyAttr' objects>, '__weakref__': <attribute '__weakref__' of 'MyAttr' objects>
这两个属性;
类调用__dict__属性,返回该类的所有属性和方法;
实例调用__dict__属性,返回的是实例相关的属性和方法;
默认情况下,类的实例有一个字典存储属性,因此,当创建大量的实例时,会消耗很大的内存,于是就有了内置属性__slots__来解决这个问题;
通过在类中定义__slots__属性来覆盖默认的__dict__行为,__slots__接受一个实例变量序列,并在每个实例中只保留足够保存每个变量值的空间,
因此,由于没有为每个实例创建__dict__属性,所以节省很多空间;
class MySlots(object): # 指定类对象所能绑定的属性 # 限制属性 # 节约内存:定义了__slots__方法后,该对象不会再自动生成__dict__属性 __slots__ = ["name"] def __init__(self,name): self.name = name ms = MySlots("yy") print(ms.__dict__) 执行结果为: print(ms.__dict__) AttributeError: 'MySlots' object has no attribute '__dict__'
在类里定义__slots__属性,并指定所能绑定的属性后,在__init__初始化方法中也只能传指定的属性,如果传__slots__没有绑定的属性,会报错;
__slots__的用法:
class Case: __slots__ = ["case_id","title","url","data","excepted"] def __init__(self): self.case_id = None self.title = None self.url = None self.data = None self.excepted = None class SaveCase: def __init__(self,file_name,sheet_name): self.file_name = file_name self.sheet_name = sheet_name def save_case(self): wb = load_workbook(self.file_name) sheet = wb[self.sheet_name] case = [] for i in range(2,sheet.max_row + 1): line_case = Case() line_case.case_id = sheet.cell(i,1).value line_case.title = sheet.cell(i,2).value line_case.url = sheet.cell(i,3).value line_case.data = sheet.cell(i,4).value line_case.excepted = sheet.cell(i,5).value case.append(line_case)
****注意:__slots__属性不能被继承,只在当前类中起作用;