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的类,其中包括nameage两个特点,以及一个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的特点和办法,包括nameagemoney以及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 自界说特点拜访

还能够经过界说一些特别办法来自界说类实例的特点拜访行为。这些特别办法能够操控特点的获取、设置和删去操作。

  1. __getattribute__办法:
    获取一个特点时,Python 会首先调用该办法。咱们能够在这个办法中自界说特点的获取行为。例如,能够在办法中检查特点是否存在,并回来相应的值。

    def __getattribute__(self, data):
        value = super().__getattribute__(data)
        return value
    
  2. __setattr__办法:
    设置一个特点时,Python 会调用该办法。咱们能够在这个办法中自界说特点的设置行为。例如,能够在办法中对特点进行类型检查,然后运用super().__setattr__()办法设置特点的值。

    def __setattr__(self, key, value):
        super().__setattr__(key, value)
    
  3. __delattr__办法:
    删去一个特点时,Python 会调用该办法。咱们能够在这个办法中自界说特点的删去行为。例如,能够在办法中执行一些清理操作或抛出反常。

    def __delattr__(self, item):
        super().__delattr__(item)
    
  4. __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")来获取目标p1name特点的值。

类似地,咱们能够运用setattr()函数来设置目标的特点值:

setattr(yongge, "age", 40)
print(yongge.age)

输出成果为:

40

上述代码中,咱们运用setattr(yongge, "age", 40)将目标yonggeage特点值设置为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命令