1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""
The idea behind this code came from a user at a random irc channel asking how to find out if a number is even. The student expanded that the %-operator that was given in the exercise wasn't enough to solve the task so I coded this example for him.

After coding for three hours I presented an initial solution to the student. Alas he didn't really grasp the code after which he thanked me for my efforts and left.

Afterwards I added support for decimal numbers and negation for reasons I don't quite understand.

Here is the execution of the module and code for your enjoyment purposes:

tappi@virtual-debian:~$ python modulo.py
True
True
True
True
True
True

"""

from __future__ import division
import re

def _add_modulus_method(cls, name, divisor, negation):

    if negation:
        neg_str = " not"
        def divisibleFunction(self):
            return self % divisor != 0
    else:
        neg_str = ""
        def divisibleFunction(self):
            return self % divisor == 0

    divisibleFunction.__doc__ = "Returns true if instance number is{1} divisible by {0}".format(divisor, neg_str)
    divisibleFunction.__name__ = name

    setattr(cls, name, divisibleFunction)

def get_getattribute(cls):

    def getattribute(self, name):
        try:
            return super(cls, self).__getattribute__(name)
        except AttributeError:
            pass

        negation = True if re.search(r"Not", name) else False

        result = re.search(r"^is(Not)?DivisibleBy(?P<divisor>\d+)$", name)
        if result is not None:
            divisor = int(result.group('divisor'))
            _add_modulus_method(cls, name, divisor, negation)
            return super(cls, self).__getattribute__(name)

        result = re.search(r"^is(Not)?DivisibleBy(?P<whole_number>\d+)point(?P<decimal_remainder>\d+)$", name)
        if result is not None:
            whole_number = result.group('whole_number')
            decimal_remainder = result.group('decimal_remainder')
            divisor = float(whole_number + "." + decimal_remainder)

            _add_modulus_method(cls, name, divisor, negation)
            return super(cls, self).__getattribute__(name)

        raise AttributeError

    return getattribute

class Int(int): pass
Int.__getattribute__ = get_getattribute(Int)

class Float(float): pass
Float.__getattribute__ = get_getattribute(Float)

if __name__  == '__main__':
    i = Int(10)
    print i.isDivisibleBy2()
    print i.isNotDivisibleBy3()
    print i.isDivisibleBy2point5()
    print i.isNotDivisibleBy3point5()

    f = Float(2.2)
    print f.isDivisibleBy2point2()
    print f.isNotDivisibleBy1point0()