【问题标题】:How do you know when looking at the list of attributes and methods listed in a dir which are attributes and which are methods?查看目录中列出的属性和方法列表时,您如何知道哪些是属性,哪些是方法?
【发布时间】:2010-10-27 04:20:24
【问题描述】:

我正在努力学习如何使用 Python 编程,并专注于更好地掌握如何使用标准和其他模块。 dir 函数在解释器中似乎非常强大,但我想知道我是否因为缺乏 OOP 背景而遗漏了什么。使用 S.Lotts 的书,我决定使用他的 Die 类来学习更多关于语法以及类和实例的使用。

这是原始代码:

class Die(object):
''' simulate a six-sided die '''
def roll(self):
    self.value=random.randrange(1,7)
    return self.value
def getValue(self):
    return self.value

我正在查看它,在创建了一些实例之后,我想知道单词 value 是否是关键字,以及 class 语句中单词 object 的用途是什么,所以我决定通过将类定义更改为以下:

class Die():
''' simulate a six-sided die '''
def roll(self):
    self.ban=random.randrange(1,7)
    return self.ban
def getValue(self):
    return self.ban

这种变化表明我从我的实例中得到了相同的行为,但是当我执行 dir 时,实例中缺少以下方法/属性:

'__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
 '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
_repr__', '__setattr__', '__str__', '__weakref__'

我还发现,当我对实例执行 dir 时,我有一个额外的关键字 -ban,我最终发现它是我实例的一个属性。这帮助我了解我可以使用 d1.ban 来访问我的实例的值。我能确定这是一个属性的唯一原因是我输入了 d1.happy 并得到了一个 AttributeError 我发现 d1.GetValue是一种附加到 Die 的方法,因为这是解释器告诉我的。

因此,当我尝试使用像 BeautifulSoup 这样的复杂但有用的模块时,我如何知道在键入 dir(instance)后列出的哪些内容是我的实例的属性或我的实例的方法>。我需要知道这一点,因为这一点告诉我,我使用属性调用方法的结果,使用方法调用实例上的函数。

这个问题可能太罗嗦了,但它确实帮助我更好地理解了属性和方法之间的区别。具体来说,当我查看在 Die 类的实例上调用 dir 的结果时,我看到了这个

['__doc__', '__module__', 'ban', 'getValue', 'roll']

因此,通过查看该列表来了解哪些是属性以及哪些是方法似乎很有用,而不必求助于反复试验或导致键入 hasattr(myInstance,suspectedAttributeName)

发布问题后我尝试了

for each in dir(d1):
    print hasattr(d1,each)

严格来说,它告诉我所有方法都是属性。但我不能调用没有 () 的方法,所以在我看来 hasattr() 具有误导性。

【问题讨论】:

    标签: python attributes methods python-datamodel


    【解决方案1】:

    这个受 Dive into Python 启发的 info 模块可以达到目的。

    def info(obj, spacing=20, collapse=1, variables=False):
        '''Print methods and their doc Strings
    
        Takes any object'''
        if variables:
        methodList = [method for method in dir(obj)]
        else:
        methodList = [method for method in dir(obj) if callable(getattr(obj,method))]
    
        #print methodList
    
    
        print '\n'.join(['%s %s' %
                (method.ljust(spacing),
                 " ".join(str(getattr(obj,method).__doc__).split()))
                for method in methodList])
    
    
    if __name__=='__main__':
        info(list)
    

    【讨论】:

    • 哇,这也很有帮助——感谢您抽出宝贵时间分享。
    【解决方案2】:

    考虑使用标准库的inspect 模块——它通常是最方便的自省方法,将大量功能打包(你可以从头开始实现它,但重用经过良好测试、设计良好的代码是一件好事)。有关所有详细信息,请参阅 http://docs.python.org/library/inspect.html,但例如 inspect.getmembers(foo, inspect.ismethod) 是获取 foo 的所有方法的绝佳方法(您将获得按名称排序的 (name, value) 对)。

    【讨论】:

      【解决方案3】:

      代替:“print hasattr(d1,each)”,尝试:“print each, type(getattr(d1,each))”。您应该会发现结果信息丰富。

      另外,代替dir() 试试help(),我认为您确实在寻找它。

      【讨论】:

      • 谢谢,这确实很有帮助
      【解决方案4】:

      理想情况下,当使用像 BeautifulSoup 这样复杂的库时,您应该查阅其文档以了解每个类提供了哪些方法。但是,在您没有易于访问的文档的极少数情况下,您可以使用以下方法检查是否存在方法。

      所有本身是对象的方法都实现了__call__ 方法,并且可以使用返回True 的callable() 方法进行检查,如果被检查的值具有__call__ 方法。

      以下代码应该可以工作。

      x = Die()
      x.roll()
      
      for attribute in dir(x) :
          print attribute, callable(getattr(x, attribute))
      

      上面的代码会为所有的方法返回 true,而对所有不可调用的属性(例如数据成员,如 ban)返回 false。但是,此方法还为任何可调用对象(如内部类)返回 True。也可以检查属性的类型是否为instancemethod

      【讨论】:

      • 谢谢你告诉我的是,如果没有文档或一些编程,我在查看有用的 dir(obj) 时无法区分
      【解决方案5】:

      严格来说,它告诉我所有方法都是属性。但我不能调用没有 () 的方法,所以在我看来 hasattr() 具有误导性。

      为什么会产生误导?如果obj.ban() 是一个方法,那么obj.ban 就是对应的属性。你可以有这样的代码:

      print obj.getValue()
      

      get = obj.getValue
      print get()
      

      如果你想获取一个对象的方法列表,你可以试试这个函数。它并不完美,因为它也会触发非方法的可调用属性,但对于 99% 的情况应该足够好:

      def methods(obj):
          attrs = (getattr(obj, n) for n in dir(obj))
          return [a for a in attrs if a.hasattr("__call__")]
      

      【讨论】:

      • 好吧 d1=Die() 然后当我输入 d1.roll 我得到 > 所以我知道 d1.roll!=d1.roll() 向我表明方法和属性是不同的。但是感谢您的回答,它有帮助
      • 方法和属性没有区别。 d1.roll 是一个属性。我建议您尝试阅读 Python 简介,例如 diveintopython.orgdocs.python.org/tutorial ,并了解函数。这可能有助于您了解方法的工作原理。
      • obj.ban() 不是方法,而是方法调用。 obj.ban 不是属性,而是绑定方法。 hasattr 不是a 的属性,它是一个内置函数。
      • Jarret-这个讨论很有帮助,我从你的放大中学到的是,真的没有捷径可走。我整个下午都在输入 obj.[item 从对象的目录列表中,试图更好地理解如何使用这个 majic。我还在另一个窗口中打开了 BeuatifulSoup 的源代码,我正在缓慢但肯定地了解如何提高效率。 Python 是我对这类语言的介绍。
      • 约翰,所以我越来越接近理解。从您的示例中,如果 obj.ban() 是一种方法; obj.ban 是该方法的一个属性。我认为我的问题不同。在我的示例中,不是 d1 对象。 d1 有一个方法 [roll],当该方法被调用(调用可能是更好的语法)时,d1 有一个属性 [ban]。由于我正在对对象进行编程,因此我想要可以应用于对象的方法以及在调用方法后应用于对象的属性。哇!如果我说 d1.roll 我得到的方法属性与方法不同?
      【解决方案6】:

      有一个内置的方法叫做 callable。您可以将它应用于任何对象,它会根据是否可以调用它返回 True/False。例如

      >>> def foo():
      ...   print "This is the only function now"
      ...
      >>> localDictionary = dir()
      >>> for item in localDictionary:
      ...   print repr(item) + "is callable: " + str(callable(locals()[item]))
      '__builtins__'is callable: False
      '__doc__'is callable: False
      '__name__'is callable: False
      'foo'is callable: True
      

      注意 locals() 调用将返回一个字典,其中包含当前范围内定义的所有内容。我这样做是因为字典中的项目只是字符串,我们需要在实际对象上运行 callable。

      【讨论】:

      • callable 已弃用,并已在 3.0 中删除。最好直接检查call
      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      相关资源
      最近更新 更多