如何判断dir列出的属性和方法中哪些是属性,哪些是方法?

5 投票
6 回答
735 浏览
提问于 2025-04-15 11:40

我正在学习Python编程,特别想更好地理解如何使用标准模块和其他模块。在解释器中,dir函数看起来非常强大,但我担心因为缺乏面向对象编程的背景,我可能错过了一些东西。于是,我决定用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 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()这个说法有点误导。

6 个回答

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__")]
4

可以考虑使用标准库中的 inspect 模块——这个模块通常是进行代码检查时最方便的选择,它把很多功能打包在一起(你可以自己从头实现这些功能,但重复使用经过充分测试和设计良好的代码是个好主意)。想了解更多细节,可以查看 http://docs.python.org/library/inspect.html。比如,使用 inspect.getmembers(foo, inspect.ismethod) 可以很方便地获取对象 foo 的所有方法(你会得到按名称排序的 (name, value) 对)。

8

不要用:"print hasattr(d1,each)",可以试试:"print each, type(getattr(d1,each))"。这样你会发现结果更有帮助。

另外,别用dir(),可以试试help(),我觉得这才是你真正想要的。

撰写回答