在Python中,特点自省是一种强壮的特性,它答应咱们在运行时检查和操作目标的特点。在本文中,咱们将讨论Python中的特点自省,并结合实际场景和代码来展现其用法。
1. 私有特点与拜访约束
Python中的私有特点是指以下划线开头的变量或办法,例如_name或_method()。尽管这种命名约定并非强制性的,只是一种常规,但它用于提示该特点或办法应该只在类内部运用,而不该该在外部直接拜访。
Python中的私有特点具有以下特点:
-
私有特点不能被外部直接拜访,但能够经过类内部的办法直接地拜访。
-
在类内部界说的办法能够拜访一切特点,包括私有特点,由于它们都在同一个效果域内。
-
子类无法承继父类的私有特点,但能够经过公有办法来拜访父类的私有特点。
接下来勇哥带你讨论怎么拜访和修正私有特点:
class YongeGe:
name= '勇哥' # 一般特点
_ager = 100 # 一般特点
__money = 109 # 私有特点
__money_empty__ = 1 # 不推荐做法
yongge = YongeGe()
print(yongge .name) # 输出: 勇哥
print(yongge ._ager ) # 输出: 100
print(yongge ._YongeGe__money ) # 输出: 109
print(yongge .__money_empty__ ) # 输出: 1
print(yongge .__money ) # 输出: AttributeError: 'YongeGe' object has no attribute '__money'
很显着看到 Python 中没有真实的私有特点,实际上双下划线开头的特点被称号重整了,即将特点名转换为_ClassName__name的办法,使其难以在外部被拜访。经过_YongGe__money能够直接拜访私有特点__money 。可是一般不要用,就比如你爹告知你剩100块了,要省点花,你非要点个海底捞一把梭哈!
总之,Python的私有特点机制主要基于命名约定,其效果是约束特点的可见性和拜访性,然后提高代码的封装性和安全性。但是,需求留意的是,这种机制只是一种建议性的标准,并不能完全避免私有特点被拜访的可能性。
2. 特点自省与目标内部状况检查
在实际开发中,咱们经常需求检查目标的特点和办法,以便理解其内部状况。Python供给了几种特点自省的办法,使咱们能够方便地检查目标的特点。
2.1 运用__dict__特点
__dict__是目标的一个特点,它包括了目标的一切特点和办法。经过拜访__dict__,咱们能够检查目标的内部状况。
例如,咱们界说了一个名为Person的类,其中包括name和age两个特点,以及一个say_hello办法。下面的代码展现了怎么经过拜访__dict__来检查目标的特点和办法:
class YongeGe:
def __init__(self, name, money):
self.name = name
self.money= money
def money(self):
print(f"Hello, my name is {self.name}.I have {self.money} dollar ")
yongge = YongeGe("勇哥", "10")
yongge .money= "1010"
yongge .__dict__["age"] = "18"
输出成果为:
{'name': '勇哥', 'money': '1010', 'age': '18'}
咱们能够看到目标yongge的特点和办法,包括name、age、money以及money办法。
需求留意的是,实例目标的__dict__特点只能拜访和修正其自身的特点和办法,而无法拜访其所属类的特点和办法。如果需求拜访类的特点和办法,能够经过类的__dict__特点来完成。
例如,咱们能够经过拜访Person.__dict__来检查类Person的一切特点和办法:
print(yongge .__dict__)
输出成果为:
{'__module__': '__main__', '__init__': <function YongeGe.__init__ at 0x0000017E50B9C5E0>, 'money': <function YongeGe.money at 0x0000017E50BBADC0>, '__dict__': <attribute '__dict__' of 'YongeGe' objects>, '__weakref__': <attribute '__weakref__' of 'YongeGe' objects>, '__doc__': None}
上述输出成果中,除了__init__、say_hello和__dict__之外,还包括其他一些特别特点和办法。经过检查类的__dict__,咱们能够获取到类的一切成员。
2.2 运用dir()函数
除了拜访目标的__dict__特点外,咱们还能够运用dir()函数来检查目标的特点和办法。
dir()函数回来一个包括目标一切特点和办法称号的列表。它不仅能够用于一般目标,还能够用于模块、类和内置类型等。
例如,下面的代码展现了怎么运用dir()函数检查目标的特点和办法:
print(dir(p1))
输出成果为:
['__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__', 'age', 'gender', 'hometown', 'name', 'say_hello']
从输出成果中,咱们能够看到目标p1的特点和办法的称号列表。
2.3 运用__slots__特点
在默许状况下,Python 类的实例会运用一个字典来存储它们的特点。这种办法关于特点很少的目标来说可能会糟蹋空间。特别是在创立大量实例时,这种空间耗费会变得更显着。
为了解决这个问题,咱们能够经过在类界说中运用__slots__来掩盖默许的__dict__行为。__slots__是一个特别特点,它承受一个特点称号的序列,并且在每个实例中只为这些特点保留满足的空间来存储特点值。由于没有为每个实例创立__dict__,所以能够节省空间。
class YongeGe:
# 界说 __slots__特点,让类实例只能绑定 __slots__中指定的特点,且不能增加其他特点
__slots__ = ('name', 'money')
def __init__(self, name_, money_):
self.name = name_
self.money = money_
if __name__ == '__main__':
yongge = YongeGe('勇哥', 100)
print(yongge.name)
setattr(yongge, 'new_attr', 100) # 输出:AttributeError: 'YongeGe' object has no attribute 'new_attr'
从上面的代码能够看到,在类中绑定了__slots__后,会约束类实例的灵敏性,不能动态增加新的特点,所以在运用这玩意的时分,要仔细想想要灵敏还是要内存?
2.4 自界说特点拜访
还能够经过界说一些特别办法来自界说类实例的特点拜访行为。这些特别办法能够操控特点的获取、设置和删去操作。
-
__getattribute__办法:
获取一个特点时,Python 会首先调用该办法。咱们能够在这个办法中自界说特点的获取行为。例如,能够在办法中检查特点是否存在,并回来相应的值。def __getattribute__(self, data): value = super().__getattribute__(data) return value -
__setattr__办法:
设置一个特点时,Python 会调用该办法。咱们能够在这个办法中自界说特点的设置行为。例如,能够在办法中对特点进行类型检查,然后运用super().__setattr__()办法设置特点的值。def __setattr__(self, key, value): super().__setattr__(key, value) -
__delattr__办法:
删去一个特点时,Python 会调用该办法。咱们能够在这个办法中自界说特点的删去行为。例如,能够在办法中执行一些清理操作或抛出反常。def __delattr__(self, item): super().__delattr__(item) -
__getattr__办法:
获取一个不存在的特点时,Python 会调用该办法。咱们能够在这个办法中自界说对不存在特点的处理逻辑。例如,能够回来默许值或许抛出反常。def __getattr__(self, item): pass
以上是一些常用的自界说特点拜访的办法。瞧瞧下面语句的执行顺序:
class MyClass:
def __init__(self):
self._data = {}
def __getattribute__(self, name):
# 自界说获取特点的行为
if name == 'attribute1':
return 'Custom Value'
elif name == 'attribute2':
return self._data[name] # 留意,这里会继续执行一次 __getattribute__
else:
return super().__getattribute__(name)
def __setattr__(self, name, value):
# 自界说设置特点的行为
if name == 'attribute2':
print("__setattr__", name, value)
self._data[name] = value + 10
else:
super().__setattr__(name, value)
def __delattr__(self, name):
# 自界说删去特点的行为
if name == 'attribute3':
self._data.pop(name, None)
else:
super().__delattr__(name)
def __getattr__(self, name):
# 处理不存在的特点
return f'Attribute "{name}" does not exist.'
if __name__ == '__main__':
obj = MyClass()
obj.attribute2 = 5
res = obj.attribute2
print(res) # 输出: __setattr__ attribute2 5 ;15
print(obj.attribute1) # 输出: Custom Value
del obj.attribute3
print(obj.attribute3) # 输出: Attribute "attribute3" does not exist.
在上面的示例中,咱们创立了一个名为MyClass的类,其中界说了__getattribute__、__setattr__、
__delattr__和__getattr__四个办法来自界说特点拜访行为。经过在这些办法中编写相应的逻辑,咱们能够操控特点的获取、设置和删去操作,然后完成自界说的特点拜访行为。
经过自界说特点拜访,咱们能够更灵敏地操控类实例的特点操作,满足特定的需求,并增强代码的可读性和可维护性。
2.5 运用getattr()、setattr()和hasattr()函数
除了检查目标的特点和办法外,咱们还能够运用getattr()、setattr()和hasattr()函数来动态地拜访和修正目标的特点。
-
getattr(obj, attr)函数用于获取目标obj的特点attr的值。 -
setattr(obj, attr, value)函数用于设置目标obj的特点attr的值为value。 -
hasattr(obj, attr)函数用于检查目标obj是否具有特点attr,如果有回来True,不然回来False。
这些函数供给了一种灵敏的办法来操作目标的特点,特别适用于需求在运行时依据条件拜访或修正特点的状况。
例如,咱们能够经过调用getattr()函数来获取目标的特点值:
name_value = getattr(yongge, "name")
print(name_value)
输出成果为:
勇哥
上述代码中,咱们运用getattr(yongge, "name")来获取目标p1的name特点的值。
类似地,咱们能够运用setattr()函数来设置目标的特点值:
setattr(yongge, "age", 40)
print(yongge.age)
输出成果为:
40
上述代码中,咱们运用setattr(yongge, "age", 40)将目标yongge的age特点值设置为30,然后再次打印yongge.age,能够看到特点值已被修正。
别的,咱们还能够运用hasattr()函数来检查目标是否具有某个特点:
has_money = hasattr(yongge, "money")
print(has_money)
输出成果为:
True
运用hasattr(yongge, "money")检查目标yongge是否具有money特点,成果为True,阐明目标具有该特点。
经过上述几种办法,咱们能够方便地进行特点自省,检查和修正目标的特点,然后更好地理解和操作代码。
3. 来点实际场景
假设咱们正在开发一个电商网站,需求处理用户购物车的相关逻辑。购物车中的产品信息以字典的办法存储在用户目标的特点中。咱们需求编写一个函数,用于核算购物车中产品的总价值。
界说一个User类,包括一个cart特点用于存储购物车中的产品信息:
class User:
def __init__(self, name):
self.name = name
self.cart = {}
def add_to_cart(self, item, price):
self.cart[item] = price
界说一个calculate_cart_value()函数,用于核算购物车中产品的总价值。在函数内部,咱们能够经过特点自省来获取购物车中的产品信息,并核算总价值:
def calculate_cart_value(user):
cart = user.__dict__.get("cart", {})
total_value = sum(cart.values())
return total_value
在上述代码中,咱们运用user.__dict__.get("cart", {})来获取购物车信息,如果用户目标中不存在cart特点,则回来一个空字典。然后,咱们运用sum(cart.values())来核算购物车中产品价格的总和。
下面是运用上述代码的示例:
# 创立用户目标
user = User("勇哥")
# 增加产品到购物车
user.add_to_cart("apple", 10)
user.add_to_cart("banana", 5)
user.add_to_cart("orange", 8)
# 核算购物车总价值
total_value = calculate_cart_value(user)
print(total_value) # 输出: 23
经过运用特点自省,咱们能够方便地拜访购物车信息,并核算总价值。特点自省还是挺重要的,面试也问得多,真实不会用也要背好飞机大炮的制造流程。可是这个玩意也不要乱用哟,频繁动态拜访,会有必定的功能开销哟~
总结
以上就是勇哥今日为各位小伙伴准备的内容,如有误,请包容并指出修正。如果你想了解更多关于Python自动化测验的常识和技巧,欢迎重视我:公众号\博客\CSDN\B站:测验玩家勇哥;我会不定期地共享更多的精彩内容。感谢你的阅览和支持!
题外话,勇哥计划把新建的技能交流群,打造成一个活泼的高质量技能群。作业中遇到的技能问题,都能够在里面咨询大家,还有作业内推的机会。有爱好的小伙伴,欢迎加我(记住补白是进群还是报名学习)
勇哥,10年落魄测验老司机,技能栈偏python,现在在一家超大型房产公司担任自动化测验主管,日常作业比较繁杂,主要担任自动化测验,功能测验、软件质量办理及人员办理。作业之余专心于为粉丝进行简历修正、面试辅导、模拟面试、材料共享、1对1自动化测验教学辅导等副业开展。现在已服务十多位小伙伴,获得高薪offer。
往期精选文章:
| python-Threading多线程之线程锁 |
| Pytest 快速入门 |
| pytest 前后置操作详谈 |
| 接口自动化之测验数据动态生成并替换 |
| requests模块该怎么封装? |
| 最通俗易懂python操作数据库 |
| python正则一篇搞掂 |
| 接口自动化怎么封装mysql操作 |
| 功能测验之必备常识 |
|
功能分析思路 |
| Python + ChatGPT来完成一个智能对话的钉钉机器人 |
| 一文看懂python怎么执行cmd命令 |
