继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Python 的内置函数 vars

2882716
关注TA
已关注
手记 70
粉丝 0
获赞 0

Python 的内置函数 vars() 是一个非常有用的工具函数,主要用于返回对象的 __dict__ 属性。它可以接受一个对象作为参数,返回该对象的属性和值的字典形式。以下是关于 vars() 函数的详细说明:

基本用法

  1. 无参数调用:当 vars() 不传入任何参数时,它会返回当前局部作用域的变量字典(类似于 locals() 函数)。这在调试函数内部状态时特别有用。

    def example():
        x = 10
        y = 20
        z = [1, 2, 3]
        print(vars())  # 输出局部变量字典 {'x': 10, 'y': 20, 'z': [1, 2, 3]}
        # 可以方便地查看当前作用域所有变量
    
    example()
    
  2. 传入对象参数:当传入一个对象时,vars() 会返回该对象的 __dict__ 属性,即包含对象实例属性的字典。这对于检查对象内部状态非常方便。

    class MyClass:
        def __init__(self):
            self.a = 1
            self.b = 2
            self._private = "secret"
    
    obj = MyClass()
    print(vars(obj))  # 输出 {'a': 1, 'b': 2, '_private': 'secret'}
    # 可以看到包括私有属性在内的所有实例属性
    

注意事项

  • 如果对象没有 __dict__ 属性(例如内置类型或使用了 __slots__ 的类),调用 vars() 会抛出 TypeError 异常。这是因为这些对象无法动态添加属性。

    num = 42
    print(vars(num))  # TypeError: vars() argument must have __dict__ attribute
    
    class SlottedClass:
        __slots__ = ['x']
        def __init__(self):
            self.x = 10
            
    sc = SlottedClass()
    print(vars(sc))  # 同样会抛出TypeError
    
  • vars()dir() 的区别:dir() 返回对象的所有属性和方法名称列表,包括继承的成员,而 vars() 只返回实例属性的字典,不包括类属性或继承属性。

    class Parent:
        class_attr = "class"
    
    class Child(Parent):
        def __init__(self):
            self.instance_attr = "instance"
    
    c = Child()
    print(dir(c))    # 包含'class_attr'和'instance_attr'等
    print(vars(c))   # 只显示{'instance_attr': 'instance'}
    

实际应用场景

  1. 调试工具:在开发过程中快速查看对象的内部状态,特别是在处理复杂对象时。

    class Debuggable:
        def __init__(self, **kwargs):
            for k, v in kwargs.items():
                setattr(self, k, v)
    
        def show_state(self):
            print("Current object state:")
            for k, v in vars(self).items():
                print(f"  {k}: {v}")
    
    dbg = Debuggable(name="test", value=100, enabled=True)
    dbg.show_state()  
    # 输出:
    # Current object state:
    #   name: test
    #   value: 100
    #   enabled: True
    
  2. 动态属性操作:配合 setattr()getattr() 实现动态属性管理,特别适合配置类对象。

    class DynamicConfig:
        pass
    
    config = DynamicConfig()
    # 批量设置属性
    attributes = {'timeout': 30, 'retries': 3, 'debug_mode': False}
    for k, v in attributes.items():
        vars(config)[k] = v
    print(vars(config))  # {'timeout': 30, 'retries': 3, 'debug_mode': False}
    
  3. 序列化预处理:在对象序列化前获取其属性字典,适用于各种序列化场景。

    import json
    import pickle
    
    class Serializable:
        def __init__(self, **kwargs):
            for k, v in kwargs.items():
                setattr(self, k, v)
    
    obj = Serializable(name="Alice", age=25, hobbies=["reading", "hiking"])
    
    # JSON序列化
    json_str = json.dumps(vars(obj))
    print(json_str)  # {"name": "Alice", "age": 25, "hobbies": ["reading", "hiking"]}
    
    # Pickle序列化
    pickled = pickle.dumps(vars(obj))
    

底层原理

vars() 的实现实际上等同于调用对象的 __dict__ 属性。在 Python 中,大多数用户自定义类的实例都会自动维护这个字典来存储实例属性。通过 vars() 访问这个字典比直接访问 __dict__ 更符合 Python 的优雅风格,同时提供了更好的可读性。

class Test:
    def __init__(self):
        self.x = 10

t = Test()
print(vars(t) is t.__dict__)  # 输出True,确实是同一个字典

版本兼容性

vars() 函数在所有 Python 版本中都可用,但在 Python 2 和 Python 3 中的行为完全一致。需要注意的是,某些优化过的对象(如使用了 __slots__ 的类)可能不支持 vars() 操作。此外,一些内置类型如int、str等也不支持vars()操作。

# Python 2和Python 3中的行为一致
class OldStyleClass:
    pass
    
class NewStyleClass(object):
    pass
    
print(vars(OldStyleClass()))  # 在Python 2中正常工作
print(vars(NewStyleClass()))  # 在所有版本中正常工作

性能考虑

虽然vars()很方便,但在性能关键的代码中直接访问__dict__可能更快,因为vars()需要额外的函数调用开销。不过在大多数情况下,这种差异可以忽略不计。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP