Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying built-in function

Let's consider any user-defined pythonic class. If I call dir(obect_of_class), I get the list of its attributes:

['__class__', '__delattr__', '__dict__', '__dir__', ... '__weakref__', 'bases', 
'build_full_name', 'candidates', ... 'update_name'].

You can see 2 types of attributes in this list:

  • built-in attributes,
  • user defined.

I need to override __dir__ so, that it will return only user defined attribltes. How I can do that?

It is clear, that if in overridden function I call itself, it gives me infinite recursion. So, I want to do somethig like this:

def __dir__(self):
        return list(filter(lambda x: not re.match('__\S*__', x), dir(self)))

but evade the infinite recursion.

In general, how can I modify a built-in function if I don't want to write it from scratch but want to modify the existing function?

like image 578
VeLKerr Avatar asked Jan 05 '16 15:01

VeLKerr


2 Answers

Use super to call parent's implementation of __dir__; avoid the recursion:

import re


class AClass:

    def __dir__(self):
        return [x for x in super().__dir__() if not re.match(r'__\S+__$', x)]

    def method(self):
        pass

>>> dir(AClass())
['method']
like image 115
falsetru Avatar answered Oct 02 '22 18:10

falsetru


Do you want to do it on your custom class or globally for dir() function?

First approach (class-only):

class MyClass:
    def f(self):
        return None

    def __dir__(self):
        return list(filter(lambda x: not re.match('__\S*__', x), super().__dir__()))


print(dir(MyClass()))  # ['f'] 

Basically what's done here is calling __dir__() of superclass (not class itself) and filtering it in subclass.

Second approach (shadowing global dir function):

import re


def dir(obj):
    return list(filter(lambda x: not re.match('__\S*__', x), __builtins__.dir(obj)))

print(dir({}))  # ['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

Here all calls to dir() would be filtered. As you can see - it'll work for all types, including built-in types.

like image 20
Łukasz Rogalski Avatar answered Oct 02 '22 18:10

Łukasz Rogalski