【问题标题】:How do I look inside a Python object?如何查看 Python 对象内部?
【发布时间】:2010-11-03 14:51:10
【问题描述】:

我开始使用 Python 在各种项目中编写代码(包括 Django Web 开发和 Panda3D 游戏开发)。

为了帮助我理解发生了什么,我想基本上“查看” Python 对象内部,看看它们是如何运行的——比如它们的方法和属性。

假设我有一个 Python 对象,我需要打印出它的内容吗?这可能吗?

【问题讨论】:

    标签: python introspection


    【解决方案1】:

    有一个很酷的工具叫做objexplore。这是一个关于如何在 pandas DataFrame 上使用其explore 函数的简单示例。

    import pandas as pd
    df=pd.read_csv('https://storage.googleapis.com/download.tensorflow.org/data/heart.csv')
    
    from objexplore import explore
    explore(df)
    

    会在你的 shell 中弹出以下内容:

    【讨论】:

      【解决方案2】:

      vars(obj) 返回对象的属性。

      【讨论】:

        【解决方案3】:

        如果您正在寻找更微妙的解决方案,您可以尝试objprint。它的一个积极方面是它可以处理嵌套对象。例如:

        from objprint import objprint
        
        class Position:
            def __init__(self, x, y):
                self.x = x
                self.y = y
        
        class Player:
            def __init__(self):
                self.name = "Alice"
                self.age = 18
                self.items = ["axe", "armor"]
                self.coins = {"gold": 1, "silver": 33, "bronze": 57}
                self.position = Position(3, 5)
        
        objprint(Player())
        

        会打印出来

        <Player
          .name = 'Alice',
          .age = 18,
          .items = ['axe', 'armor'],
          .coins = {'gold': 1, 'silver': 33, 'bronze': 57},
          .position = <Position
            .x = 3,
            .y = 5
          >
        >
        

        【讨论】:

          【解决方案4】:

          在 Python 3.8 中,您可以使用 __dict__ 打印出对象的内容。例如,

          class Person():
             pass
          
          person = Person()
          
          ## set attributes
          person.first = 'Oyinda'
          person.last = 'David'
          
          ## to see the content of the object
          print(person.__dict__)  
          
          {"first": "Oyinda", "last": "David"}
          

          【讨论】:

            【解决方案5】:

            已经有很多好的技巧了,但是最短和最简单的(不一定是最好的)还有待提及:

            object?
            

            【讨论】:

            • 它有效,但如果对象是一个大列表,你会很糟糕
            【解决方案6】:

            尝试使用:

            print(object.stringify())
            
            • 其中object 是您尝试检查的对象的变量名。

            这会打印出格式精美的选项卡式输出,显示对象中键和值的所有层次结构。

            注意:这适用于 python3。不确定它是否适用于早期版本

            更新:这不适用于所有类型的对象。如果您遇到其中一种类型(如 Request 对象),请改用以下类型之一:

            • dir(object())

            import pprint 然后: pprint.pprint(object.__dict__)

            【讨论】:

            • 不适用于 'Request' 对象 "'Request' 对象没有属性 'stringify'"
            【解决方案7】:

            如果有兴趣查看对象myobj对应的函数源码,可以输入iPythonJupyter Notebook

            myobj??

            【讨论】:

              【解决方案8】:

              虽然其他人已经提到了pprint,但我想添加一些上下文。

              pprint 模块提供了“漂亮打印”任意 可以用作输入的 Python 数据结构 口译员。如果格式化的结构包含不是 基本的 Python 类型,表示可能无法加载。这 如果对象(例如文件、套接字、类或 包括实例,以及许多其他内置对象 不能表示为 Python 常量。

              pprint 可能会受到具有 PHP 背景且正在寻找var_dump() 的替代品的开发人员的高需求。

              使用pprint()vars() 混合可以很好地转储具有dict 属性的对象,这会返回模块、类、实例等的__dict__ 属性:

              from pprint import pprint
              pprint(vars(your_object))
              

              所以,no need for a loop

              要转储 全局本地范围 中包含的所有变量,只需使用:

              pprint(globals())
              pprint(locals())
              

              locals() 显示在函数中定义的变量。
              other usages 中使用相应名称作为字符串键访问函数也很有用:

              locals()['foo']() # foo()
              globals()['foo']() # foo()
              

              类似地,使用dir() 查看模块的内容,或对象的属性。

              还有更多。

              【讨论】:

              • 我尝试从 opencv 学习匹配的结构,但没有运气# python3 orb.py Traceback (最近一次调用最后):文件“orb.py”,第 47 行,在 pprint (matches[0]) TypeError: 'module' object is not callable print(matches[0]) # python3 orb.py Traceback (last recent call last): File "orb.py", line 48, in pprint( vars(matches[0])) TypeError: vars() 参数必须有 dict 属性
              【解决方案9】:
              import pprint
              
              pprint.pprint(obj.__dict__)
              

              pprint.pprint(vars(obj))
              

              【讨论】:

              • 虽然此代码可能会回答问题,但提供有关 如何 和/或 为什么 解决问题的附加上下文将改善答案的长期性价值。
              • pprint.pprint(vars(obj))print(str(obj.__dict__).replace(',',',\n')) 的包装器吗?(合法问题)因为我尝试了这个答案,期望得到比print(str(obj.__dict__).replace(',','\n')) 得到的更多信息
              • @dmb 不仅仅是一个包装器。您可以阅读源代码。你在这里 -> github.com/python/cpython/blob/main/Lib/pprint.py#L150
              【解决方案10】:

              Python 具有一组强大的自省功能。

              看看下面built-in functions

              type()dir() 对于分别检查对象的类型及其属性集特别有用。

              【讨论】:

              • 不知道这个词是“内省”。这是一个很大的帮助!以及你给我的所有功能......谢谢!
              • property、classmethod 和 staticmethod 与自省无关。这些方法都创建了特殊类型的对象,可用于定义具有特殊行为的类,但对检查这些类或构造没有帮助。
              • 下面@Brian 的回答向您展示了如何从python 中查看各种python 对象的源代码。这就是我最初正在寻找的东西,我相信我不会孤单。 (可能值得在这个答案中引用他的答案,因为它是最被接受的。)
              • 我认为这是一个糟糕的答案。它没有为我们提供解决方案,而是为我们提供了与文档中相关的所有内容
              • @IshanSrivastava 是对的。你不应该提供答案的链接,你应该提供答案。
              【解决方案11】:

              检查代码的两个很棒的工具是:

              1. IPython。一个 python 终端,允许您使用制表符完成进行检查。

              2. EclipsePyDev plugin。它有一个出色的调试器,允许您在给定的位置中断并通过将所有变量作为树浏览来检查对象。您甚至可以使用嵌入式终端在该位置尝试代码或键入对象并按“。”让它为您提供代码提示。

              【讨论】:

                【解决方案12】:

                试试ppretty

                from ppretty import ppretty
                
                
                class A(object):
                    s = 5
                
                    def __init__(self):
                        self._p = 8
                
                    @property
                    def foo(self):
                        return range(10)
                
                
                print ppretty(A(), indent='    ', depth=2, width=30, seq_length=6,
                              show_protected=True, show_private=False, show_static=True,
                              show_properties=True, show_address=True)
                

                输出:

                __main__.A at 0x1debd68L (
                    _p = 8, 
                    foo = [0, 1, 2, ..., 7, 8, 9], 
                    s = 5
                )
                

                【讨论】:

                  【解决方案13】:
                  """Visit http://diveintopython.net/"""
                  
                  __author__ = "Mark Pilgrim (mark@diveintopython.org)"
                  
                  
                  def info(object, spacing=10, collapse=1):
                      """Print methods and doc strings.
                  
                      Takes module, class, list, dictionary, or string."""
                      methodList = [e for e in dir(object) if callable(getattr(object, e))]
                      processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
                      print "\n".join(["%s %s" %
                                       (method.ljust(spacing),
                                        processFunc(str(getattr(object, method).__doc__)))
                                       for method in methodList])
                  
                  if __name__ == "__main__":
                      print help.__doc__
                  

                  【讨论】:

                  • 如果您只是在打印件周围添加括号,这在 python 3 中可以正常工作。
                  【解决方案14】:

                  如果您对此 GUI 感兴趣,请查看objbrowser。它使用 Python 标准库中的检查模块进行底层对象自省。

                  【讨论】:

                    【解决方案15】:

                    有一个专门为此目的构建的 python 代码库:inspect 在 Python 2.7 中引入

                    【讨论】:

                      【解决方案16】:

                      如果您想查看活动对象内部,那么 python 的 inspect 模块是一个很好的答案。通常,它用于获取在磁盘上某个源文件中定义的函数的源代码。如果您想获取解释器中定义的实时函数和 lambda 的源代码,您可以使用 dill 中的 dill.source.getsource。它还可以从 curries 中定义的绑定或未绑定的类方法和函数中获取代码……但是,如果没有封闭对象的代码,您可能无法编译该代码。

                      >>> from dill.source import getsource
                      >>> 
                      >>> def add(x,y):
                      ...   return x+y
                      ... 
                      >>> squared = lambda x:x**2
                      >>> 
                      >>> print getsource(add)
                      def add(x,y):
                        return x+y
                      
                      >>> print getsource(squared)
                      squared = lambda x:x**2
                      
                      >>> 
                      >>> class Foo(object):
                      ...   def bar(self, x):
                      ...     return x*x+x
                      ... 
                      >>> f = Foo()
                      >>> 
                      >>> print getsource(f.bar)
                      def bar(self, x):
                          return x*x+x
                      
                      >>> 
                      

                      【讨论】:

                        【解决方案17】:

                        我很惊讶还没有人提到帮助!

                        In [1]: def foo():
                           ...:     "foo!"
                           ...:
                        
                        In [2]: help(foo)
                        Help on function foo in module __main__:
                        
                        foo()
                            foo!
                        

                        帮助让您阅读文档字符串并了解类可能具有的属性,这非常有帮助。

                        【讨论】:

                        • 然后你使用这里提到的其他技术。但如果文档字符串可用,请考虑它。
                        • 我不确定python在过去几年是否更新了这个函数,但是“help(object_name)”以高度结构化的格式提供了一个完整的概述。是一个守门员。谢谢。
                        【解决方案18】:

                        其他人已经提到了 dir() 内置,这听起来像您正在寻找的,但这里有另一个很好的提示。许多库——包括大多数标准库——都以源代码形式分发。这意味着您可以很容易地直接阅读源代码。诀窍在于找到它。例如:

                        >>> import string
                        >>> string.__file__
                        '/usr/lib/python2.5/string.pyc'
                        

                        *.pyc 文件已编译,因此删除尾随的“c”并在您喜欢的编辑器或文件查看器中打开未编译的 *.py 文件:

                        /usr/lib/python2.5/string.py
                        

                        我发现这对于发现诸如从给定 API 引发的异常之类的事情非常有用。这种细节在 Python 世界中很少有详细记录。

                        【讨论】:

                          【解决方案19】:

                          如果这是为了探索以了解发生了什么,我建议查看IPython。这添加了各种快捷方式来获取对象文档、属性甚至源代码。例如附加一个“?”到函数将为对象提供帮助(实际上是“帮助(obj)”的快捷方式,而使用两个?(“func??”)将显示源代码(如果可用)。

                          还有很多额外的便利,比如制表符补全、漂亮的结果打印、结果历史记录等,这使得这种探索性编程非常方便。

                          对于内省的更多程序化使用,dir()vars()getattr 等基本内置函数将很有用,但值得您花时间查看 inspect 模块。要获取函数的来源,请使用“inspect.getsource”,例如,将其应用于自身:

                          >>> print inspect.getsource(inspect.getsource)
                          def getsource(object):
                              """Return the text of the source code for an object.
                          
                              The argument may be a module, class, method, function, traceback, frame,
                              or code object.  The source code is returned as a single string.  An
                              IOError is raised if the source code cannot be retrieved."""
                              lines, lnum = getsourcelines(object)
                              return string.join(lines, '')
                          

                          inspect.getargspec 在处理包装或操作函数时也经常有用,因为它会给出函数参数的名称和默认值。

                          【讨论】:

                            【解决方案20】:

                            object.__dict__

                            【讨论】:

                            • vars(object) 就是为此而生的。
                            • 实际上from pprint import pprint; pprint(vars(object)) 让我对我的对象的内容有了一个非常好的看法。谢谢@liberforce
                            • 在字符串中查看对象及其内容的最佳方式
                            • 这是查看实现任何表示方法的对象或像 googleapiclient.errors.HttpError 这样的对象的好方法,当您打印它们时,它们肯定会打印出不足的信息,谢谢@mtasic85
                            【解决方案21】:

                            如果您想查看参数和方法,正如其他人指出的那样,您可以使用pprintdir()

                            如果要查看内容的实际值,可以这样做

                            object.__dict__

                            【讨论】:

                              【解决方案22】:

                              pprint 和 dir 一起工作很棒

                              【讨论】:

                                【解决方案23】:

                                此外,如果你想查看列表和字典,你可以使用 pprint()

                                【讨论】:

                                  【解决方案24】:

                                  你可以在 shell 中使用 dir() 列出对象的属性:

                                  >>> dir(object())
                                  ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
                                  

                                  当然还有inspect模块:http://docs.python.org/library/inspect.html#module-inspect

                                  【讨论】:

                                    【解决方案25】:

                                    首先,阅读源代码。

                                    其次,使用dir()函数。

                                    【讨论】:

                                    • 源代码比 dir() 提供更多信息,并且是一个更好的养成习惯。
                                    • 我不同意。 dir() 的速度要快得多,在 99% 的情况下,您可以结合 help() 找出您需要的内容。
                                    • 我同意通常没用。很多时候,对 dir() 的简单调用就足够了,从而省去了查看源代码的麻烦。
                                    • 有时在运行时检查对象可能很有用,但读取源代码则不然。例如。 httplib.py 类及其方法:)。
                                    猜你喜欢
                                    • 2021-12-27
                                    • 2018-07-11
                                    • 1970-01-01
                                    • 2011-11-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2016-12-17
                                    • 2019-04-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多