我正在努力学习使用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语句中使用了word对象,所以我决定通过将类定义更改为以下内容:
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__'
我还想到,当我在一个实例上做了一个目录时,我有一个额外的关键字 - 禁止,我最终想到的是我的实例的一个属性。这有助于我理解我可以使用 d1.ban 来访问我的实例的值。我能弄清楚这是一个属性的唯一原因是我输入了 d1.happy 并得到了 AttributeError 我发现了 d1.GetValue 是一种附在Die上的方法,因为这就是翻译告诉我的。
因此,当我尝试使用像BeautifulSoup这样复杂但有用的模块时,如何在输入 dir(instance)。我需要知道这一点,因为这个问题告诉我,通过属性我调用方法的结果和方法,我在我的实例上调用一个函数。
这个问题可能过于冗长,但确实有助于我更好地理解属性和方法之间的区别。具体来说,当我看到在我的Die类的实例上调用dir的结果时,我看到了这个
['__doc__', '__module__', 'ban', 'getValue', 'roll']
因此,通过查看列表中的属性和方法而不必诉诸试验和错误或者输入 hasattr(myInstance,suspAttributeName)来了解它似乎很有用。 / p>
在发布我试过的问题之后
for each in dir(d1):
print hasattr(d1,each)
它严格地告诉我所有方法都是属性。但是我不能在没有()的情况下调用方法,所以在我看来hasattr()是误导性的。
答案 0 :(得分:7)
而不是:“print hasattr(d1,each)
”,请尝试:“print each, type(getattr(d1,each))
”。你应该找到有用的结果。
此外,代替dir()
试试help()
,我认为您真的在寻找。
答案 1 :(得分:4)
考虑使用标准库的inspect
模块 - 它通常是最自省的内省方法,包含大量功能(您可以从头开始实现,但重用经过良好测试,设计良好的代码是好事)。有关所有详细信息,请参阅http://docs.python.org/library/inspect.html,但例如inspect.getmembers(foo, inspect.ismethod)
是获取foo所有方法的绝佳方法(您将按名称排序(name, value)
对。)
答案 2 :(得分:2)
它严格地告诉我所有方法都是属性。但是我不能在没有()的情况下调用方法,所以在我看来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__")]
答案 3 :(得分:2)
这个来自Dive to 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)
答案 4 :(得分:1)
理想情况下,在使用像BeautifulSoup这样的复杂库时,您应该查阅其文档以了解每个类提供的方法。但是,在极少数情况下,如果您没有易于访问的文档,则可以使用以下方法检查方法是否存在。
所有方法本身都是对象,它们实现__call__
方法,并且如果要检查的值具有True
方法,则可以使用返回__call__
的callable()方法进行检查。
以下代码应该有效。
x = Die()
x.roll()
for attribute in dir(x) :
print attribute, callable(getattr(x, attribute))
以上代码对所有方法都返回true,对所有非可调用属性(如ban等数据成员)返回false。但是,此方法还为任何可调用对象(如内部类)返回True
。您还可以检查属性的类型是否为instancemethod
答案 5 :(得分:1)
有一个名为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。