Python 当查看目录中列出的属性和方法列表时,您如何知道哪些是属性,哪些是方法?
我正在努力学习用Python编程,并专注于更好地掌握如何使用标准模块和其他模块。dir函数在解释器中似乎非常强大,但我想知道我是否因为缺少OOP背景而遗漏了什么。使用S.Lotts的书,我决定使用他的Die类来学习更多关于语法以及类和实例的使用 以下是原始代码: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
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)