Как вы узнаете, просматривая список атрибутов и методов, перечисленных в директории, которые являются атрибутами, а какие - методами? - PullRequest
4 голосов
/ 19 мая 2009

Я работаю над тем, чтобы научиться программировать на Python и сосредоточен на том, чтобы лучше понять, как использовать стандартные и другие модули. Функция dir кажется действительно мощной в интерпретаторе, но мне интересно, что я что-то упустил из-за отсутствия фона ООП. Используя книгу С.Лоттса, я решил использовать его класс 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 каким-то образом ключевым словом и как это делает использование объекта 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__'

Я также понял, что когда я делал dir для экземпляра, у меня было дополнительное ключевое слово - ban , которое я, наконец, понял, было атрибутом моего экземпляра. Это помогло мне понять, что я могу использовать d1.ban для доступа к значению моего экземпляра. Единственная причина, по которой я смог выяснить, что это атрибут, - я набрал d1.happy и получил AttributeError Я понял, что d1.GetValue - это метод привязанный к Die, потому что это то, что сказал мне переводчик.

Поэтому, когда я пытаюсь использовать какой-то сложный, но полезный модуль, например BeautifulSoup, как я могу узнать, какие из перечисленных вещей являются атрибутами моего экземпляра или методами моего экземпляра после ввода dir (instance), Мне нужно было бы знать это, потому что это возрождение научило меня, что с атрибутами я вызываю результат метода, а с методами я вызываю функцию в моем экземпляре.

Этот вопрос, вероятно, слишком многословен, но, несомненно, помог мне лучше понять разницу между атрибутами и методами. В частности, когда я смотрю на результат вызова dir для экземпляра моего класса Die, я вижу это

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

Так что было бы полезно узнать, посмотрев в этот список, какие атрибуты и методы являются необходимыми, без необходимости прибегать к методам проб и ошибок или в результате набрать hasattr (myInstance, suspectedAttributeName) .

После размещения вопроса я попробовал

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

, который строго говорит мне, что все методы являются атрибутами. но я не могу вызвать метод без () , поэтому мне кажется, что hasattr () вводит в заблуждение.

Ответы [ 6 ]

7 голосов
/ 19 мая 2009

Вместо: "print hasattr(d1,each)" попробуйте: "print each, type(getattr(d1,each))". Вы должны найти результаты информативными.

Также вместо dir() попробуйте help(), который, я думаю, вы действительно ищете.

4 голосов
/ 19 мая 2009

Подумайте об использовании модуля inspect стандартной библиотеки - это часто самый удобный подход к самоанализу, объединяющий значительные функциональные возможности (вы могли бы реализовать это с нуля, но хорошо использовать повторно проверенный, хорошо разработанный код - это хорошо ). Подробности смотрите в http://docs.python.org/library/inspect.html, но, например, inspect.getmembers(foo, inspect.ismethod) - отличный способ получить все методы foo (вы получите (name, value) пар, отсортированных по имени).

2 голосов
/ 19 мая 2009

Этот info модуль, вдохновленный Dive into Python, служит цели.

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 голосов
/ 19 мая 2009

, что строго говорит мне, что все методы являются атрибутами. но я не могу вызвать метод без (), поэтому мне кажется, что 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__")]
1 голос
/ 19 мая 2009

Существует встроенный метод, называемый 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 () вернет словарь, содержащий все, что определено в вашей текущей области видимости. Я сделал это, потому что элементы из словаря - просто строки, и нам нужно запустить вызываемый объект на реальном объекте.

1 голос
/ 19 мая 2009

В идеале, при использовании сложной библиотеки, такой как BeautifulSoup, вам следует обратиться к ее документации, чтобы узнать, какие методы предоставляет каждый класс. Однако в редком случае, когда у вас нет легко доступной документации, вы можете проверить наличие методов, используя следующие.

Все методы, которые сами являются объектами, реализуют метод __call__ и могут быть проверены с помощью метода callable (), который возвращает True, если проверяемое значение имеет метод __call__.

Следующий код должен работать.

x = Die()
x.roll()

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

Приведенный выше код вернул бы true для всех методов и false для всех не вызываемых атрибутов (таких как элементы данных, такие как ban). Однако этот метод также возвращает True для любых вызываемых объектов (например, внутренних классов). Вы также можете проверить, является ли тип атрибута instancemethod

...