测开之面向对象进阶篇・《属性自省》
Posted 七月的小尾巴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了测开之面向对象进阶篇・《属性自省》相关的知识,希望对你有一定的参考价值。
私有属性
类里面定义的变量叫做属性,那么类属性有两种,分为:公有属性和私有属性。
私有属性的定义:
- 单下滑线开头:_attr
- 双下划线开头:__attr
其中单下划线开头的在外部可以直接访问,双下滑线,在外部访问不了,因为在python底层修改了属性的名称。
在上方图中,我们可以看到,双下滑定义的私有属性,名称被改成了 _Test__test
,如果想要访问该属性方法,需要调用 _Test__test
才能访问。
在python中,并没有偶正真的是私有化支持,但可用下划线得到伪私有。在python 的使用习惯中,通常下划线定义的属性,都不会强制性进行修改。
python中__dict__方法
类调用 __dict__
方法,会以字典的形式,返回类所有属性的方法
实例调用 __dict__
方法,返回的值实例相关的实例属性。
内置属性__slots__
默认情况下,类的实例有一个字典用于存储属性。这个对于具有很少实例变量的对象会浪费空间。当创建大量实例时,控件消耗可能会变的尖锐。
可以通过在类定义中,定义 __slots__
来覆盖默认 __dict__
的行为。 __slots__
声明接受一个实例变量序列,并在每个实例中只保留足够保存每个变量值的空间。因为没有每个实例创建 __dict__
,所以节省空间。
class MyTest(object):
pass
t = MyTest()
# 查看该类的所有属性和方法
print(MyTest.__dict__)
class Mytest(object):
__slots__ = ['attr', 'name']
t = MyTest()
# 报错,此时 __dict__ 没有创建,被 slots 覆盖了
print(MyTest.__dict__)
我们可以通过 slots 属性来限制类实例的属性,只能绑定 slots 指定的属性。
自定义访问属性
可以定义下面的方法来自定义类实例的属性方法的含义。
object.__getatter__
: 当属性查找到在通常的地方,没有找到属性时调用object.__getattribute__
: 查找属性时,第一时间会调用该方法object.__setattr__
:设置属性方法时,调用该方法设置的属性object.__delattr__
:删除属性
class Test:
def __getattr__(self, item):
print("没有找到属性,触发 AttributeError 异常时会调用此方法")
def __getattribute__(self, item):
print("没有设置属性,会调用此方法")
object.__getattribute__(self, item)
def __delattr__(self, item):
print("属性被删除了")
object.__delattr__(self, item)
def __setattr__(self, key, value):
print("查看属性,首先会进入该方法")
object.__setattr__(self, key, value)
习题
了解了python的内置属性之后,我们来做一道习题,方便我们更好的理解内置属性。
自定义一个类
1、对这个类创建的对象,进行属性限制,对象只能设置这个三个属性: title money data
2、通过相关机制对设置的属性类型进行限制,title只能设置字符串类型数据
money设置为int类型数据 data可以设置为任意类型
3、通过相关机制实现,data 属性不能进行删除
4、当money设置的值少于0时,确保查询出来的值为0
class MyClass(object):
__slots__ = ['title', 'money', 'data']
def __init__(self, title, money, data):
self.title = title
self.money = money
self.data = data
def __getattr__(self, item):
return "类中未定义{}属性".format(item)
def __setattr__(self, key, value):
# 判断 title 只能设置字符串
if key == "title":
if isinstance(value, str):
super().__setattr__(key, value)
else:
raise TypeError("title 属性只能设置字符串")
# 判断 money 只能设置为 int
elif key == 'money':
if isinstance(value, int):
super().__setattr__(key, value)
else:
raise TypeError("money 属性只能设置为 int")
else:
super().__setattr__(key, value)
def __getattribute__(self, item):
# 获取 money 属性
if item == 'money':
value = super().__getattribute__(item)
# 判断如果 money 的值小于0,则返回0
if value < 0:
value = 0
return value
return super().__getattribute__(item)
def __delattr__(self, item):
# 判断当 data 属性被删除时,raise 异常
if item == 'data':
raise AttributeError("{0}属性不能被删除".format(item))
super().__delattr__(item)
if __name__ == '__main__':
m = MyClass("22", 0, 0)
print(m.title, m.money1, m.data)
del m.money
以上是关于测开之面向对象进阶篇・《属性自省》的主要内容,如果未能解决你的问题,请参考以下文章