1、私有属性
Python并没有真正的私有化支持,但可用下划线得到伪私有,有一项大多数 Python 代码都遵循
的习惯:带有下划线,前缀的名称应被视为非公开的 API 的一部分(无论是函数、 方法还是数据
成员)。它应被视为实现细节
1、私有的属性和方法为双下滑先开头的
2、在类里面不管是私有的属性,还是方法,都只能在类里面使用
3、私有的属性和方法是不能继承
2、 dict
类调用 dict 属性,返回类属性和所有方法的字典。
实列调用 dict 属性,返回的值实列相关的实例属性
class Demo3:
attr = 100
# 类的私有属性
_attr = 900 # 声明式的私有属性(程序员之间默认的私有属性)
__attr2 = 200 # 真正的私有属性
def __init__(self):
# 对象的私有属性
self.__name = 'demo3'
self.name = 'demo3333'
@classmethod
def work(cls):
# 获取私有的类属性
print(cls.__attr2)
# 调用私有的类方法
cls.__work2()
print('----work----')
# 类私有的方法
@classmethod
def __work2(cls):
print("---work2------")
def work4(self):
# 在类里面获取私有实例属性
print(self.__name)
# 调用私有的实例方法
self.__work5()
print('----work4-----')
# 对象的私有方法(私有的实例方法)
def __work5(self):
print('-------work5-----')
print(Demo3.__dict__)
d = Demo3()
print(d.__dict__)
# 结果
{'__module__': '__main__', 'attr': 100, '_attr': 900, '_Demo3__attr2': 200, '__init__': <function Demo3.__init__ at 0x0000023BA8D03400>, 'work': <classmethod object at 0x0000023BA8D1A978>, '_Demo3__work2': <classmethod object at 0x0000023BA8D1A9E8>, 'work4': <function Demo3.work4 at 0x0000023BA8D03598>, '_Demo3__work5': <function Demo3.__work5 at 0x0000023BA8D03620>, '__dict__': <attribute '__dict__' of 'Demo3' objects>, '__weakref__': <attribute '__weakref__' of 'Demo3' objects>, '__doc__': None}
{'_Demo3__name': 'demo3', 'name': 'demo3333'}
3、内置属性 slots
默认情况下,类的实例有一个字典用于存储属性。这对于具有很少实例变量的对象会浪费空间。当创建
大量实例时,空间消耗可能会变得尖锐。
可以通过在类定义中定义 __ slots __ 来覆盖默认 __dict__ 行为。 __ slots __ 声明接受一个实例变量序
列,并在每个实例中只保留足够保存每个变量值的空间。因为没有为每个实例创建 __ dict __ ,所以
节省空间。
定义过slots属性来限制类实例的属性,只能绑定slots指定的属性。不能添加slots之外的属性
__slots__ 的两个作用:
1、限制实例对象的属性
2、阻止属性字典的创建(对象不会拥有__dict__)
class Demo:
# 通过__slots__属性可以限制类的实例 的属性
#
# __slots__ = ['name', 'age']
__slots__ = []
def work(self):
print("---work----")
d = Demo()
d.work()
# d.name = 99
d.age = 999
#结果
Traceback (most recent call last):
---work----
File "D:/LTT/XXX.py", line 48, in <module>
d.age = 999
AttributeError: 'Demo' object has no attribute 'age'
4、自定义属性访问
可以定义下面的方法来自定义类实例的属性访问的含义(访问、赋值或者删除 x.name )。
# 当属性查找在通常的地方没有找到该属性时调用
object.__getattr__
# 查找属性时,第一时间会调用该方法
object.__getattribute__
# 设置属性时,调用该方法设置属性,
object.__setattr__
# 在del obj.attr删除属性时触发
object.__delattr__
class Demo(object):
def __init__(self, name, age):
"""
:param name: str类型
:param age: int类型
"""
print("____init_____方法开始")
self.name = name
self.age = age
print("____init_____方法结束")
def __setattr__(self, key, value):
"""在__setattr__方法中可以对属性的创建过程做干预"""
# 属性设置的魔术方法
print("____setattr_____方法开始")
if key == 'name':
if isinstance(value, str):
# 调用父类的__setattr__方法设置属性
super().__setattr__(key, value)
else:
raise TypeError('name属性的值必须为字符串')
elif key == 'age':
if isinstance(value, int):
# 调用父类的__setattr__方法设置属性
super().__setattr__(key, value)
else:
raise TypeError('age属性的值必须为int类型')
else:
super().__setattr__(key, value)
# print("属性{},值为{}".format(key, value))
def __delattr__(self, item):
"""删除属性的方法"""
if item == 'name':
raise AttributeError('name属性不支持删除')
else:
# 调用父类的属性进行删除操作
super().__delattr__(item)
def __getattribute__(self, item):
"""获取属性的方法"""
print("获取的属性名为:", item)
# 调用父类的方法去获取属性
try:
value = super().__getattribute__(item)
except AttributeError:
value = None
return value
# 同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用
def __getattr__(self, item):
"""获取的属性不存在时,触发的方法"""
print('__getattr__方法', item)
pass
dd = Demo('musen', 999)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
dd.sex = '男'
print(dd.__dict__)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
____setattr_____方法开始
获取的属性名为: __dict__
{'name': 'musen', 'age': 999, 'sex': '男'}
del dd.age
delattr(dd, 'sex')
print(dd.__dict__)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
____setattr_____方法开始
__delattr__方法 age
__delattr__方法 sex
获取的属性名为: __dict__
{'name': 'musen'}
print(dd.age1)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
获取的属性名为: age1
None
# 类中没有定义__getattribute__
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
__getattr__方法 age1
None
hasattr(dd, 'age')
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
获取的属性名为: age