Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f27d777

Browse files
mapattr
1 parent 64cc22f commit f27d777

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

‎README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
- [listinherited.py](listinherited.py) Mix-in class that provides a formatted print() or str() (Use dir() to collect both instance attr and names inherited from its classes)
2525
- [listinherited2.py](listinherited2.py) Same as listinherited.py, but more formatted
2626
- [listtree.py](listtree.py) Trace the entire class and all its object's attrs at and above self
27+
- [mapattrs.py](mapattrs.py) Map all attributes on or inherited by an
28+
instance to the instance or class from which they are inherited.
2729

2830
---
2931

‎mapattrs.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""
2+
File: mapattrs.py (3.x + 2.x)
3+
4+
Main tool: mapattrs() map all attributes on or inherited by an
5+
instance t othe instance or class from which they are inherited.
6+
7+
Assumes dir() give all attributes of an instance. To simulate
8+
inheritance, uses eitehr the class's MRO tuple, which gives the
9+
search order for new-style classes (and all in 3.x), or a recursive
10+
traversal to infer the DFLR order of classic classes in 2.x
11+
12+
Also here: inheritance() gives version-neutral class ordering;
13+
assorted dictionary tools using 3.x/2.7 comprehensions.
14+
"""
15+
16+
import pprint
17+
18+
19+
def trace(X, label='', end='\n'):
20+
print(label + pprint.pformat(X) + end) # Print nicely
21+
22+
23+
def filterdictvals(D, V):
24+
"""
25+
dict D with entries for valeus V removed.
26+
filterdictvals(dict(a=1, b=2, c=1), 1) => {'b': 2}
27+
"""
28+
return {K: V2 for (K, V2) in D.items() if V2 != V}
29+
30+
31+
def invertdict(D):
32+
"""
33+
dict D with values changed to keys (grouped by values).
34+
Values must all be hashable to work as dict/set keys.
35+
invertdict(dict(a=1, b=2, c=1)) => {1: ['a', 'c'], 2: 'b'}
36+
"""
37+
def keysof(V):
38+
return sorted(K for K in D.keys() if D[K] == V)
39+
return {V: keysof(V) for V in set(D.values())}
40+
41+
42+
def dflr(cls):
43+
"""
44+
Classics depth-first left-to-right order of class tree at cls.
45+
Cycles not possible: Python disallows on __bases__ changes.
46+
"""
47+
here = [cls]
48+
for sup in cls.__bases:
49+
here += dflr(sup)
50+
return here
51+
52+
53+
def inheritance(instance):
54+
"""
55+
Inheritance order sequnce: new-style (MRO) or classic (DFLR)
56+
"""
57+
if (hasattr(instance.__class__, '__mro__')):
58+
return (instance,) + instance.__class__.__mro__
59+
else:
60+
return [instance] + dflr(instance.__class__)
61+
62+
63+
def mapattrs(instance, withobject=False, bysource=False):
64+
"""
65+
dict with keys giving all inherited attributes of instance,
66+
with values giving the object that each is inherited from.
67+
withobject: False=remove object built-in class attributes
68+
bysource: True=group result by objects instead of attributes.
69+
Supports classes with slot that preclude __dict__ in instance.
70+
"""
71+
attr2obj = {}
72+
inherits = inheritance(instance)
73+
for attr in dir(instance):
74+
for obj in inherits:
75+
if hasattr(obj, '__dict__') and attr in obj.__dict__:
76+
attr2obj[attr] = obj
77+
break
78+
79+
if not withobject:
80+
attr2obj = filterdictvals(attr2obj, object)
81+
82+
return attr2obj if not bysource else invertdict(attr2obj)
83+
84+
85+
if __name__ == '__main__':
86+
print('Classics classes in 2.x, new-style in 3.x')
87+
class A: attr1 = 1
88+
class B(A): attr2 = 2
89+
class C(A): attr1 = 3
90+
class D(B, C): pass
91+
I = D()
92+
print("Py=>%s" % I.attr1)
93+
trace(inheritance(I), 'INH\n')
94+
trace(mapattrs(I), 'ATTRS\n')
95+
trace(mapattrs(I, bysource=True), 'OBJS\n')
96+
97+
print('New-style classes in 2.x and 3.x')
98+
class A(object): attr1 = 1
99+
class B(A): attr2 = 2
100+
class C(A): attr1 = 3
101+
class D(B, C): pass
102+
I = D()
103+
print("Py=>%s" % I.attr1)
104+
trace(inheritance(I), 'INH\n')
105+
trace(mapattrs(I), 'ATTRS\n')
106+
trace(mapattrs(I, bysource=True), 'OBJS\n')

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /