3

How do you know attributes vs methods in Python object? When using the dir method it only list everything for example dir('string').

Djangonow
  • 413
  • 1
  • 4
  • 9
  • 3
    Neither of the two linked questions are answering the OP's. They're asking how to **test** the difference between method and attribute, not what they are or how to get the full list. – GPhilo Jul 27 '20 at 12:22

1 Answers1

5

You can test the attributes's type:

from types import MethodType
from pprint import pprint

class A(object):
  def __init__(self) -> None:
    self._field = 3
    self._callable_field = lambda x: x
  
  def my_method(self):
    pass

  @classmethod
  def my_static_method(cls):
    pass

  def __str__(self) -> str:
    return repr(self)

A.another_method = lambda self: None

a = A()
pprint([(d, type(getattr(a,d)) is MethodType) for d in dir(a)])

prints

[('__class__', False),
 ('__delattr__', False),
 ('__dict__', False),
 ('__dir__', False),
 ('__doc__', False),
 ('__eq__', False),
 ('__format__', False),
 ('__ge__', False),
 ('__getattribute__', False),
 ('__gt__', False),
 ('__hash__', False),
 ('__init__', True),
 ('__init_subclass__', False),
 ('__le__', False),
 ('__lt__', False),
 ('__module__', False),
 ('__ne__', False),
 ('__new__', False),
 ('__reduce__', False),
 ('__reduce_ex__', False),
 ('__repr__', False),
 ('__setattr__', False),
 ('__sizeof__', False),
 ('__str__', True),              # <<<<<<<<<<
 ('__subclasshook__', False),
 ('__weakref__', False),
 ('_callable_field', False),     # <<<<<<<<<<
 ('_field', False),              # <<<<<<<<<<
 ('another_method', True),       # <<<<<<<<<<
 ('my_method', True),            # <<<<<<<<<<
 ('my_static_method', True)]     # <<<<<<<<<<

Note that this won't print True for builtin methods that are not explicitly defined in the class definition (or attached later, see __str__ and another_method above). Note, also, that unlike testing for callable, this actually catches the distinction between methods and callable attributes.

GPhilo
  • 18,519
  • 9
  • 63
  • 89
  • "Note that this only prints True for attributes that are explicitly defined in the class definition" not true, consider, `A.another_method = lambda self: None` – juanpa.arrivillaga Jul 27 '20 at 12:35
  • @juanpa.arrivillaga Good point. What I'm trying to say is, builtin methods won't be marked as such, only those explicitly `def`ined (such as `__init__`) are marked as `True`. Dunno how to word that differently though. – GPhilo Jul 27 '20 at 12:38
  • @juanpa.arrivillaga Tried to reword it, not sure it's clearer though – GPhilo Jul 27 '20 at 12:41