Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当查看目录中列出的属性和方法列表时,您如何知道哪些是属性,哪些是方法?_Python_Attributes_Methods_Python Datamodel - Fatal编程技术网

Python 当查看目录中列出的属性和方法列表时,您如何知道哪些是属性,哪些是方法?

Python 当查看目录中列出的属性和方法列表时,您如何知道哪些是属性,哪些是方法?,python,attributes,methods,python-datamodel,Python,Attributes,Methods,Python Datamodel,我正在努力学习用Python编程,并专注于更好地掌握如何使用标准模块和其他模块。dir函数在解释器中似乎非常强大,但我想知道我是否因为缺少OOP背景而遗漏了什么。使用S.Lotts的书,我决定使用他的Die类来学习更多关于语法以及类和实例的使用 以下是原始代码: class Die(object): ''' simulate a six-sided die ''' def roll(self): self.value=random.randrange(1,7) return se

我正在努力学习用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是否是一个关键字,以及单词object在class语句中的用法,因此我决定将类定义更改为以下内容:

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()是有误导性的

严格地说,所有方法都是属性。但是我不能在没有()的情况下调用方法,所以在我看来hasattr()是有误导性的

为什么会产生误导?如果
obj.ban()
是一个方法,则
obj.ban
是相应的属性。您可以使用如下代码:

print obj.getValue()

如果要获取对象上的方法列表,可以尝试此函数。它不是完美的,因为它也会触发非方法的可调用属性,但对于99%的情况来说应该足够好了:

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

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

所有方法(它们本身都是对象)都实现了
\uuuu call\uuu
方法,并且可以使用callable()方法进行检查,如果要检查的值具有
\uu call\uu
方法,则该方法返回
True

下面的代码应该可以工作

x = Die()
x.roll()

for attribute in dir(x) :
    print attribute, callable(getattr(x, attribute))

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

有一个名为callable的内置方法。您可以将其应用于任何对象,它将根据是否可以调用而返回True/False。e、 g

>>> 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。

而不是:“
打印hasattr(d1,each)
”,尝试:“
打印each,键入(getattr(d1,each))
”。你应该会发现结果信息丰富


另外,请尝试使用我认为您真正需要的
help()
,来代替
dir()

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

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)

callable已被弃用,并已在3.0中删除。最好直接检查call.well d1=Die(),然后当我键入d1.roll时,我得到了,这样我就知道d1.roll!=d1.roll()这对我来说意味着方法和属性是不同的。但感谢您的回答,这有助于方法和属性没有什么不同。d1.roll是一个属性。我建议您尝试阅读Python简介,如或,并了解函数。这可能有助于您了解方法的工作原理。
obj.ban()
不是方法,而是方法调用。
obj.ban
不是属性,而是绑定方法。
hasattr
不是
a
的属性,它是一个内置函数。Jarret-这个讨论很有帮助,我从你的放大中学到,实际上没有捷径。我一直在键入o
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)