Skip to content

Commit 5a1c49c

Browse files
authored
Create README.md
1 parent b0f472b commit 5a1c49c

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Python Disinheritance
2+
**_Disinheritance_** is the removal of inherited methods and attributes to prevent (i.e., "disinherit") unwanted capabilities in subclass types. Nominally, the approach to disinheritance is by individually overriding the unwanted methods and attributes of a subclass. However, depending on the behavior of a parent class, this can be a laborious process, especially if a large amount of parent methods and attributes are unwanted. Another approach is by structuring types and subclassed types to ensure limited inheritance (e.g., with "mixin" use), which could require more complexity in creating appropriate subclass types.
3+
4+
When other approaches are impractical, the `disinheritance` module may be a viable alternative. The `disinherit` decorator object automatically overrides unwanted inherited methods and attributes and prevents their use in subclass instances, except where specified as exemptions. Features of `disinherit` include:
5+
6+
* Exemptions can be one or more type methods/attributes or even entire types in the subclass MRO (though exemptions are managed internally by type/containing type and declaration order)
7+
* Exemptions can be from anywhere in the MRO and will be applied to the subclass as overrides (unless already overriden in the subclass)
8+
* `dir()` call on a subclass instance will not include disinherited methods/attributes
9+
* Attempts at attribute retrieval of disinherited methods/attributes from an instance produce attribute errors
10+
* `help()` call on a subclass type will show disinherited methods/attributes as not implemented (i.e., as the `NotImplemented` singleton)
11+
* Invalid exemptions (i.e., types and type methods/attributes not in the MRO) are silently ignored
12+
* Subclass `__dir__` and `__getattribute__` methods are wrapped to both maintain original functionality and account for disinherited methods/attributes
13+
* Exemptions are explicitly specified using an `exempt` keyword argument for the sake of clarity and deliberate use in style
14+
15+
## Example:
16+
```
17+
from disinheritance import disinherit
18+
19+
@disinherit()
20+
class StrStandin(str):
21+
"""object does not function like a regular str"""
22+
23+
@disinherit(exempt=str.upper)
24+
class StrUpper(str):
25+
"""object allows upper method"""
26+
```
27+
28+
```
29+
>>> standin = StrStandin('hello, world!')
30+
>>> upperonly = StrUpper('spam and eggs')
31+
```
32+
33+
```
34+
>>> dir(standin)
35+
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__format__',
36+
'__getattribute__', '__getstate__', '__hash__', '__init__', '__init_subclass__',
37+
'__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
38+
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
39+
```
40+
41+
```
42+
>>> standin.upper()
43+
Traceback (most recent call last):
44+
File "<pyshell#87>", line 1, in <module>
45+
value.upper()
46+
File ".../disinheritance.py", line 188, in __getattribute__
47+
raise error
48+
AttributeError: 'StrStandin' object has no attribute 'upper'
49+
```
50+
51+
```
52+
>>> upperonly.upper()
53+
'SPAM AND EGGS'
54+
```

0 commit comments

Comments
 (0)