4

I'm learning python and one of the built-in functions being taught is dir() -- the course describes it as 'returning the directory of valid attributes for an object,' but what are an object's attributes?

I think I see some member functions in the returned list of attributes, __len__ I assume refers to len(), but what are all these other things listed?

Course description

Also, what does it mean, it can be incomplete?

This is my first question and I wouldn't ask it if I didn't already spend 45 minutes trying to figure this out.

Selcuk
  • 57,004
  • 12
  • 102
  • 110
lincoln
  • 45
  • 5
  • you may need to see [this](https://stackoverflow.com/a/45062077/10727144) – Amit Nanaware Mar 12 '19 at 04:31
  • You can see object (aka. instance) attributes as all names (also called variables) existing in the namespace of an object. They can reference any type of object including methods and stuff inherited from the class and its superclasses. – Klaus D. Mar 12 '19 at 04:39

4 Answers4

1

You're confusing a few things and are possibly confused about a few confusing things.

__len__ is not referring to len(), rather len(something) will call the __len__ method of something. Any object that has a __len__ method can be asked for its length by calling len(something). Note how this is different from something.len() and how it is more legible than something.__len__().

An object's attributes in Python include what you would normally consider its attributes, as well as all of its property and method names. So for this example:

class T:
    def __init__(self):
        self.x = 10

    def afunc(self):
        return 20

    @property
    def y(self):
        return self.x

Any instance of T would include in its attributes x, afunc and y. An object's attributes also include all the attributes of its base classes (so what classes it inherits from), ultimately always including the attributes of object.

The remark about it being incomplete is in in reference to objects that don't have a __dir__ attribute to be called by the dir() function. In those cases, the dir() function will look at its __dict__ attribute (if available) and as a result it may not offer a complete list of attributes - note that this isn't the case for most objects.

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • Thank you for your answer, so, in effect, an object's attributes are the member functions and variables it's inherited from its class as well as the object's own methods and variables, right? – lincoln Mar 13 '19 at 01:13
  • Yes, that's pretty much it. In general, it's common to call 'variables' of objects 'attributes' and 'functions' of objects 'methods', which is why Python is a bit confusing, since methods of objects also show up in their lists of attributes. – Grismar Mar 13 '19 at 08:05
  • I see, thank you for the explanation! And as I understand it, functions inherited from an object's class are also called member functions, right? – lincoln Mar 14 '19 at 01:08
  • I think the phrase 'member function' is more common when speaking about C++, due to the way C++ implements OOP methods. But if you're speaking in general object-orientation terms, method is more common. Of course, a hardcore C++ developer may insist that 'method' is a Javaism, but quite frankly, I think the earlier languages like Smalltalk deserve the credit (and they typically used 'method'). However, the OO standard work 'Design Patterns' uses 'operations', just to avoid the whole discussion it seems - if all the standards are bad, you just invent a new one, right? – Grismar Mar 14 '19 at 02:29
0

Depends on what type of object you are talking about. Say the object in question is a class, then all the attributes that come under class's namespace are listed by dir. And that includes any methods, class level variables that are specifically declared by the user + anything that is inherited. Remember classes inherit from 'object' which provides a bunch of special methods

See if below code makes sense:

class A(object):
    def __init__(self, a):
        self.a = a
    def m(self):
        print("in method")
    @property
    def p(self):
        print("in prop")
    def __get__(self, obj, owner):
        print("in get")
        return self
    def __call__(self, *args):
        print("call")

If you do dir on class A, you will see all attributes under namespace of A + the ones inherited from object as below. Also try dir(object) to see what are the specific 'object' attributes

['__call__',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__get__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'm',
 'p']

Note that self.a isn't listed as self.a belongs to instance and not the class itself

To add, your object numbers is of type list and hence all attributes of list are listed (see dir(list))

ranjith
  • 361
  • 4
  • 14
0

Let's say you have a class Person

class Person:
    name = "Samuel"
    age = 50
    country = "India"

    def method1(self):
        print("Method 1")

print(dir(Person))

The output of the above program looks like this:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 
'age', 'country', 'method1', 'name']

What you can see from the above output is that it returns a sorted list of valid attributes for that object. If you look at the class Person:

name, age, country are attributes and method1 is the method of that class. Hence when you use dir(Person), it will display all the attributes of that class.

The default dir() mechanism behaves differently with different types of objects, as it attempts to produce the most relevant, rather than complete, information:

  • If the object is a module object, the list contains the names of the module’s attributes.
  • If the object is a type or class object, the list contains the names of its attributes, and recursively of the attributes of its bases.
  • Otherwise, the list contains the object’s attributes’ names, the names of its class’s attributes, and recursively of the attributes of its class’s base classes.

For example,

a = [1,2,3,45]
print(dir(a))

This will print:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', 
 '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
 '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', 
 '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', 
 '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', 
 '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', 
 '__setattr__', '__setitem__', '__sizeof__', '__str__', 
 '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 
 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Here, you can see few other attributes names insert, pop, remove etc. If you check with previous list, they were not present. It's because different types of objects have different attributes and with these attributes you can use these objects in different forms. You can use a.pop(2) to remove an element etc.

len I assume refers to len()

Generally, len() is the public interface you use to get the length of an object. The __len__ method is the implementation that an object that supports the concept of length is expected to implement. len() calls __len__()

I think I see some member functions in the returned list of attributes, len I assume refers to len(), but what are all these other things listed?

Visit the following link, https://docs.python.org/3.6/reference/datamodel.html#object.dir. Majority of them are listed here. There usages are also described.

PROTOCOL
  • 371
  • 9
  • 17
0

Those are the methods that the object superclass has. And any object that inherits from this attains these properties. Now I think you are confusing yourself with __len__() and len(something).

len() is a function that is brought into scope by default. What it simply does is it calls the __len__() function that resides in that object.

Say you called len([1,2,3,4]) this will call the __len__() method that is present inside the class List i.e the class which this list object was created from.

Various functions use these dunder methods for their own purposes.

here's an example

class Test:
    def __myfunc__(self):
        return "I have been called"

def testFunc(object):
    return object.__myfunc__()

test = Test()

testFunc(test)

'I have been called'

Same way many of these functions also work.

Vineeth Sai
  • 3,389
  • 7
  • 23
  • 34
  • Interesting, so this isn't something unique to built in functions, if I created another class like this `class Test_2: def __myfunc__(self): return "I was called"` Then created an object of that class type `test2 = Test_2()` Then, calling `testFunc(test)` would still return 'I have been called', but `testFunc(test2)` same function, different parameter, will return 'I was called' Is that right? – lincoln Mar 13 '19 at 01:33