百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Python 中 必须掌握的 20 个核心函数——dir()函数

itomcoil 2025-09-21 16:23 5 浏览

dir()是Python中用于查看对象属性和方法的内置函数,它是探索和调试Python对象的强大工具。

一、dir()的基本用法

1.1 方法签名

dir([object])
  • object:要检查的对象(可选)
  • 返回:对象的属性和方法名称列表

1.2 基础示例

# 查看当前作用域的变量
print(dir())  # 显示当前模块的所有名称

# 查看内置函数和变量
print(dir(__builtins__))

# 查看对象的属性和方法
my_list = [1, 2, 3]
print(dir(my_list))  # 显示列表的所有方法

二、dir()的深入解析

2.1 不同对象的dir()输出

# 字符串对象
s = "hello"
print("String methods:", [m for m in dir(s) if not m.startswith('_')])

# 列表对象
lst = [1, 2, 3]
print("List methods:", [m for m in dir(lst) if not m.startswith('_')])

# 字典对象
d = {"a": 1}
print("Dict methods:", [m for m in dir(d) if not m.startswith('_')])

# 自定义对象
class MyClass:
    def __init__(self):
        self.attribute = "value"
    def method(self):
        pass

obj = MyClass()
print("Custom object:", dir(obj))

2.2 dir()与__dict__的区别

class Example:
    class_var = "class value"
    
    def __init__(self):
        self.instance_var = "instance value"
    
    def method(self):
        pass

obj = Example()

# dir() 显示所有可访问的属性和方法
print("dir():", [x for x in dir(obj) if not x.startswith('__')])

# __dict__ 只显示实例属性
print("__dict__:", obj.__dict__)

# 类属性可以通过dir()看到,但不在__dict__中
print("'class_var' in dir():", 'class_var' in dir(obj))
print("'class_var' in __dict__:", 'class_var' in obj.__dict__)

三、实际应用场景

3.1 调试和探索

# 快速查看对象的能力
def explore_object(obj):
    """探索对象的属性和方法"""
    print(f"Object type: {type(obj)}")
    print("Methods and attributes:")
    for attr in dir(obj):
        if not attr.startswith('__'):  # 过滤掉魔术方法
            attr_obj = getattr(obj, attr)
            print(f"  {attr}: {type(attr_obj)}")

# 探索不同的对象
explore_object([])   # 列表
explore_object({})   # 字典
explore_object("")   # 字符串

3.2 动态编程

# 检查对象是否支持特定操作
def supports_operation(obj, operation):
    """检查对象是否支持特定操作"""
    return operation in dir(obj)

# 使用示例
data = [1, 2, 3]
print("Supports append:", supports_operation(data, 'append'))
print("Supports upper:", supports_operation(data, 'upper'))

# 动态调用方法
def safe_call(obj, method_name, *args, **kwargs):
    """安全地调用对象方法"""
    if hasattr(obj, method_name) and callable(getattr(obj, method_name)):
        method = getattr(obj, method_name)
        return method(*args, **kwargs)
    else:
        raise AttributeError(f"Object has no method '{method_name}'")

# 使用示例
s = "hello"
print(safe_call(s, 'upper'))      # HELLO
print(safe_call(s, 'split', 'l')) # ['he', '', 'o']

3.3 对象比较和分析

def compare_objects(obj1, obj2):
    """比较两个对象的属性和方法"""
    attrs1 = set(dir(obj1))
    attrs2 = set(dir(obj2))
    
    common = attrs1 & attrs2
    unique1 = attrs1 - attrs2
    unique2 = attrs2 - attrs1
    
    print("Common attributes:", sorted(common))
    print("Unique to obj1:", sorted(unique1))
    print("Unique to obj2:", sorted(unique2))
    
    return common, unique1, unique2

# 比较列表和元组
list_obj = [1, 2, 3]
tuple_obj = (1, 2, 3)
compare_objects(list_obj, tuple_obj)

四、高级用法与技巧

4.1 过滤和分类属性

def analyze_object(obj):
    """分析对象的属性类型"""
    attributes = dir(obj)
    
    # 分类属性
    methods = [attr for attr in attributes if callable(getattr(obj, attr))]
    properties = [attr for attr in attributes if not callable(getattr(obj, attr))]
    
    # 过滤魔术方法
    public_methods = [m for m in methods if not m.startswith('__')]
    public_properties = [p for p in properties if not p.startswith('__')]
    
    # 过滤私有方法(单下划线)
    private_methods = [m for m in methods if m.startswith('_') and not m.startswith('__')]
    
    return {
        'all_attributes': attributes,
        'public_methods': public_methods,
        'public_properties': public_properties,
        'private_methods': private_methods,
        'magic_methods': [m for m in methods if m.startswith('__')]
    }

# 使用示例
analysis = analyze_object([])
print("List public methods:", analysis['public_methods'])

4.2 与inspect模块配合使用

import inspect

def detailed_inspection(obj):
    """详细的对象检查"""
    print("=== DIR() ===")
    print([attr for attr in dir(obj) if not attr.startswith('__')])
    
    print("\n=== INSPECT ===")
    # 获取方法签名等信息
    for attr in dir(obj):
        if not attr.startswith('__') and callable(getattr(obj, attr)):
            method = getattr(obj, attr)
            try:
                sig = inspect.signature(method)
                print(f"{attr}{sig}")
            except ValueError:
                print(f"{attr} - cannot inspect signature")

# 检查字符串对象
detailed_inspection("hello")

4.3 创建对象浏览器

class ObjectBrowser:
    """交互式对象浏览器"""
    
    def __init__(self, obj):
        self.obj = obj
        self.history = []
    
    def explore(self):
        """启动交互式探索"""
        while True:
            self.show_status()
            command = input("Enter attribute name or command (q to quit): ").strip()
            
            if command == 'q':
                break
            elif command == 'b':
                self.go_back()
            elif command == '':
                continue
            else:
                self.explore_attribute(command)
    
    def show_status(self):
        """显示当前状态"""
        print(f"\nCurrent object: {type(self.obj)}")
        print("Attributes:", [attr for attr in dir(self.obj) if not attr.startswith('__')])
    
    def explore_attribute(self, attr_name):
        """探索特定属性"""
        if hasattr(self.obj, attr_name):
            attr_value = getattr(self.obj, attr_name)
            print(f"{attr_name}: {type(attr_value)} = {repr(attr_value)}")
            
            # 如果是可调用对象,显示签名
            if callable(attr_value):
                try:
                    import inspect
                    sig = inspect.signature(attr_value)
                    print(f"Signature: {attr_name}{sig}")
                except ValueError:
                    pass
            
            # 询问是否深入探索
            if input("Explore this attribute? (y/n): ").lower() == 'y':
                self.history.append(self.obj)
                self.obj = attr_value
        else:
            print(f"Attribute '{attr_name}' not found")
    
    def go_back(self):
        """返回上一级"""
        if self.history:
            self.obj = self.history.pop()
        else:
            print("Already at top level")

# 使用示例
# browser = ObjectBrowser([1, 2, 3])
# browser.explore()

五、常见问题解答

5.1 dir()显示的内容包括什么?

class Example:
    class_attr = "class value"
    
    def __init__(self):
        self.instance_attr = "instance value"
    
    def method(self):
        pass

obj = Example()

# dir() 包括:
# 1. 实例属性
# 2. 类属性
# 3. 继承的属性和方法
# 4. 魔术方法
print("dir() includes:", len(dir(obj)), "items")

5.2 如何过滤dir()的结果?

obj = [1, 2, 3]

# 过滤掉魔术方法
public_attrs = [attr for attr in dir(obj) if not attr.startswith('__')]
print("Public attributes:", public_attrs)

# 只显示方法
methods = [attr for attr in dir(obj) if callable(getattr(obj, attr))]
print("Methods:", methods)

# 只显示属性(非方法)
properties = [attr for attr in dir(obj) if not callable(getattr(obj, attr))]
print("Properties:", properties)

5.3 dir()与help()的区别

obj = "hello"

# dir() 显示名称列表
print("dir():", dir(obj))

# help() 显示详细文档
# help(obj)  # 取消注释查看帮助信息

# 结合使用
def get_method_info(obj, method_name):
    """获取方法的详细信息"""
    if hasattr(obj, method_name):
        method = getattr(obj, method_name)
        print(f"=== {method_name} ===")
        print("Signature:", end=" ")
        try:
            import inspect
            print(inspect.signature(method))
        except ValueError:
            print("Cannot determine signature")
        print("Docstring:", method.__doc__)
    else:
        print(f"Method '{method_name}' not found")

get_method_info(obj, 'upper')

六、最佳实践和模式

6.1 调试工具函数

def debug_object(obj, name="object"):
    """调试对象信息的工具函数"""
    print(f"=== DEBUG: {name} ===")
    print(f"Type: {type(obj)}")
    print(f"ID: {id(obj)}")
    print(f"Length: {len(obj) if hasattr(obj, '__len__') else 'N/A'}")
    
    # 显示所有属性
    attrs = dir(obj)
    print(f"\nAttributes ({len(attrs)}):")
    for attr in sorted(attrs):
        if not attr.startswith('__'):
            try:
                attr_value = getattr(obj, attr)
                print(f"  {attr}: {type(attr_value)} = {repr(attr_value)}")
            except Exception as e:
                print(f"  {attr}: ERROR - {e}")

# 使用示例
debug_object([1, 2, 3], "my_list")

6.2 动态接口检查

def implements_interface(obj, interface_methods):
    """检查对象是否实现特定接口"""
    missing_methods = []
    for method in interface_methods:
        if not hasattr(obj, method) or not callable(getattr(obj, method)):
            missing_methods.append(method)
    
    if missing_methods:
        raise TypeError(f"Object missing required methods: {missing_methods}")
    return True

# 定义接口
class Serializable:
    REQUIRED_METHODS = ['serialize', 'deserialize']
    
    @classmethod
    def check_implementation(cls, obj):
        return implements_interface(obj, cls.REQUIRED_METHODS)

# 使用示例
class MyData:
    def serialize(self):
        return "serialized"
    
    def deserialize(self, data):
        self.data = data

try:
    Serializable.check_implementation(MyData())
    print("MyData implements Serializable interface")
except TypeError as e:
    print(e)

6.3 对象导出工具

def export_object_info(obj, include_private=False):
    """导出对象信息为字典"""
    info = {
        'type': str(type(obj)),
        'module': obj.__class__.__module__,
        'attributes': {},
        'methods': {}
    }
    
    for attr_name in dir(obj):
        # 过滤私有属性
        if not include_private and attr_name.startswith('_'):
            continue
            
        try:
            attr_value = getattr(obj, attr_name)
            
            if callable(attr_value):
                info['methods'][attr_name] = {
                    'type': 'method',
                    'signature': str(get_callable_signature(attr_value))
                }
            else:
                info['attributes'][attr_name] = {
                    'type': 'attribute',
                    'value': repr(attr_value),
                    'value_type': str(type(attr_value))
                }
                
        except Exception as e:
            info['attributes'][attr_name] = {
                'type': 'error',
                'error': str(e)
            }
    
    return info

def get_callable_signature(func):
    """获取可调用对象的签名"""
    try:
        import inspect
        return inspect.signature(func)
    except ValueError:
        return "Unknown signature"

# 使用示例
info = export_object_info([1, 2, 3])
import json
print(json.dumps(info, indent=2))

七、总结最佳实践

  1. 探索工具:使用dir()快速了解对象的 capabilities
  2. 调试辅助:在调试时使用dir()查看对象状态
  3. 动态编程:结合getattr()和hasattr()实现动态行为
  4. 接口检查:验证对象是否支持所需的方法
def export_object_info(obj, include_private=False):
    """导出对象信息为字典"""
    info = {
        'type': str(type(obj)),
        'module': obj.__class__.__module__,
        'attributes': {},
        'methods': {}
    }
    
    for attr_name in dir(obj):
        # 过滤私有属性
        if not include_private and attr_name.startswith('_'):
            continue
            
        try:
            attr_value = getattr(obj, attr_name)
            
            if callable(attr_value):
                info['methods'][attr_name] = {
                    'type': 'method',
                    'signature': str(get_callable_signature(attr_value))
                }
            else:
                info['attributes'][attr_name] = {
                    'type': 'attribute',
                    'value': repr(attr_value),
                    'value_type': str(type(attr_value))
                }
                
        except Exception as e:
            info['attributes'][attr_name] = {
                'type': 'error',
                'error': str(e)
            }
    
    return info

def get_callable_signature(func):
    """获取可调用对象的签名"""
    try:
        import inspect
        return inspect.signature(func)
    except ValueError:
        return "Unknown signature"

# 使用示例
info = export_object_info([1, 2, 3])
import json
print(json.dumps(info, indent=2))

七、总结最佳实践

  1. 探索工具:使用dir()快速了解对象的 capabilities
  2. 调试辅助:在调试时使用dir()查看对象状态
  3. 动态编程:结合getattr()和hasattr()实现动态行为
  4. 接口检查:验证对象是否支持所需的方法

相关推荐

《Queendom》宣布冠军!女团MAMAMOO四人激动落泪

网易娱乐11月1日报道据台湾媒体报道,南韩女团竞争回归的生死斗《Queendom》昨(10/31)晚播出大决赛,并以直播方式进行,6组女团、女歌手皆演唱新歌,并加总前三轮的赛前赛、音源成绩与直播现场投...

正确复制、重写别人的代码,不算抄袭

我最近在一篇文章提到,工程师应该怎样避免使用大量的库、包以及其他依赖关系。我建议的另一种方案是,如果你没有达到重用第三方代码的阈值时,那么你就可以自己编写代码。在本文中,我将讨论一个在重用和从头开始编...

HTML DOM tr 对象_html event对象

tr对象tr对象代表了HTML表格的行。HTML文档中出现一个<tr>标签,就会创建一个tr对象。tr对象集合W3C:W3C标签。集合描述W3Ccells返回...

JS 打造动态表格_js如何动态改变表格内容

后台列表页最常见的需求:点击表头排序+一键全选。本文用原生js代码实现零依赖方案,涵盖DOM查询、排序算法、事件代理三大核心技能。效果速览一、核心思路事件入口:为每个<th>绑...

连肝7个晚上,总结了66条计算机网络的知识点

作者|哪吒来源|程序员小灰(ID:chengxuyuanxiaohui)计算机网络知识是面试常考的内容,在实际工作中经常涉及。最近,我总结了66条计算机网络相关的知识点。1、比较http0....

Vue 中 强制组件重新渲染的正确方法

作者:MichaelThiessen译者:前端小智来源:hackernoon有时候,依赖Vue响应方式来更新数据是不够的,相反,我们需要手动重新渲染组件来更新数据。或者,我们可能只想抛开当前的...

为什么100个前端只有1人能说清?浏览器重排/重绘深度解析

面试现场的"致命拷问""你的项目里做过哪些性能优化?能具体讲讲重排和重绘的区别吗?"作为面试官,我在秋招季连续面试过100多位前端候选人,这句提问几乎成了必考题。但令...

HTML DOM 介绍_dom4j html

HTMLDOM(文档对象模型)是一种基于文档的编程接口,它是HTML和XML文档的编程接口。它可以让开发人员通过JavaScript或其他脚本语言来访问和操作HTML和XML文档...

JavaScript 事件——“事件流和事件处理程序”的注意要点

事件流事件流描述的是从页面中接收事件的顺序。IE的事件流是事件冒泡流,而NetscapeCommunicator的事件流是事件捕获流。事件冒泡即事件开始时由最具体的元素接收,然后逐级向上传播到较为不...

探秘 Web 水印技术_水印制作网页

作者:fransli,腾讯PCG前端开发工程师Web水印技术在信息安全和版权保护等领域有着广泛的应用,对防止信息泄露或知识产品被侵犯有重要意义。水印根据可见性可分为可见水印和不可见水印(盲水印)...

国外顶流网红为流量拍摄性侵女学生?仅被封杀三月,回归仍爆火

曾经的油管之王,顶流网红DavidDobrik复出了。一切似乎都跟他因和成员灌酒性侵女学生被骂到退网之前一样:住在950万美元的豪宅,开着20万美元的阿斯顿马丁,每条视频都有数百万观看...人们仿佛...

JavaScript 内存泄漏排查方法_js内存泄漏及解决方法

一、概述本文主要介绍了如何通过Devtools的Memory内存工具排查JavaScript内存泄漏问题。先介绍了一些相关概念,说明了Memory内存工具的使用方式,然后介绍了堆快照的...

外贸独立站,网站优化的具体内容_外贸独立站,网站优化的具体内容有哪些

Wordpress网站优化,是通过优化代码、数据库、缓存、CSS/JS等内容,提升网站加载速度、交互性和稳定性。网站加载速度,是Google搜索引擎的第一权重,也是SEO优化的前提。1.优化渲染阻塞。...

这8个CSS工具可以提升编程速度_css用什么编译器

下面为大家推荐的这8个CSS工具,有提供函数的,有提供类的,有提取代码的,还有收集CSS的统计数据的……请花费两分钟的时间看完这篇文章,或许你会找到意外的惊喜,并且为你的编程之路打开了一扇新的大门。1...

vue的理解-vue源码 历史 简介 核心特性 和jquery区别 和 react对比

一、从历史说起Web是WorldWideWeb的简称,中文译为万维网我们可以将它规划成如下的几个时代来进行理解石器时代文明时代工业革命时代百花齐放时代石器时代石器时代指的就是我们的静态网页,可以欣...