Python: Declaring Dynamic Attributes

The examples below are in Python 3.5, but otherwise this post is applicable to both Python 2.x and 3.x


This is a companion discussion topic for the original entry at http://amir.rachum.com/blog/2016/10/05/python-dynamic-attributes/

This is useful in 3.x, but in 2.x object doesn’t have dir defined, so it seems that to implement dir I have to give up the default behavior of dir on my class completely.

class A(object):
    def __dir__(self):
        return super(A, self).__dir__() + ['foo']
    

a = A()

dir(a)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-143-d23808581cf8> in <module>()
----> 1 dir(a)

<ipython-input-141-f1a7775ab9fe> in __dir__(self)
      1 class A(object):
      2     def __dir__(self):
----> 3         return super(A, self).__dir__() + ['foo']
      4 

AttributeError: 'super' object has no attribute '__dir__'

Try replacing that line with:
return dir(super(A, self)) + ['foo']
in either Python 2 or 3.

Thanks @henryschreineriii, but now I run into the following:

class A(object):
    def __dir__(self):
         return dir(super(A, self)) + ['foo']

a = A() 
a.b = 'c'
dir(a)
['__class__',
 '__delattr__',
 '__doc__',
 '__format__',
 '__get__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__self__',
 '__self_class__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__thisclass__',
 'foo']

# Where's attribute b?

class B(object): pass
b.c = 'd'
dir(b)
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'c']
# Attribute c displayed correctly here

Attribute b is in

 __dict__.keys()

This way works in python 2.7

def __dir__(self):
    output = self.__dict__.keys() +  dir(self.__class__)
    output += ['foo']
    return sorted(set(output))

What IDE is the this post targeting?
I cannot make this work into PyCharm, python 3.5

This article gave me a nice start on my own twist on something similar

.