cdxcore.pretty#
Classes
|
A |
|
Class mimicing an ordered dictionary. |
- class cdxcore.pretty.PrettyHierarchy(copy=None, **kwargs)[source]#
Bases:
PrettyObjectA
cdxcore.pretty.PrettyObjectwhich can easily create hierarchies ofcdxcore.pretty.PrettyObject’s.This works:
from cdxcore.pretty import PrettyHierarchy r = PrettyHierarchy() r.a = 1 r.x.b = 2 assert r.a == 1 assert isinstance(r.x,PrettyHierarchy) assert r.x.b == 2
Some oddities:
from cdxcore.pretty import PrettyHierarchy r = PrettyHierarchy() r.A = 1 print( r.a ) # -> prints an empty PrettyHierarchy _ = r.b # generates an empty PrettyHierarchy assert set(r) == {'A','a','b'} # all above created entries.
Runtime semantics can be confusing as
cdxcore.pretty.PrettyHierarchycreates objects on the fly if an attrbute is not known. Hence typos can generate confusing error messages: assume we have some code that creates acdxcore.pretty.PrettyHierarchy:data = PrettyHierarchy() data = ... data.center = compute_centre()
Somewhere else we then access
data.centreinstread ofdata.center:np.sum( data.centre )
This raises
TypeError: 'PrettyHierarchy' object is not callableinstead of anAttributeError.Note that
["x"]keeps working as expected, i.e. it will fail if ‘x’ does not exist.
- class cdxcore.pretty.PrettyObject(copy=None, **kwargs)[source]#
Bases:
MutableMappingClass mimicing an ordered dictionary.
Example:
from cdxcore.pretty import PrettyObject pdct = PrettyObject() pdct.x = 1 pdct['y'] = 2 print( pdct['x'], pdct.y ) # -> prints 1 2
The object mimics a dictionary:
print(pdct) # -> '{'x': 1, 'y': 2}' u = dict( pdct ) print(u) # -> {'x': 1, 'y': 2} u = { k: 2*v for k,v in pdct.items() } print(u) # -> {'x': 2, 'y': 4} l = list( pdct ) print(l) # -> ['x', 'y']
Important: attributes starting with ‘__’ cannot be accessed with item
[]notation. In other words:pdct = PrettyObject() pdct.__x = 1 # fine _ = pdct['__x'] # <- throws an exception
Access by Index Position
cdxcore.pretty.PrettyObjectretains order of construction. To access its members by index position, use thecdxcore.pretty.PrettyObject.at_posattribute:print(pdct.at_pos[1]) # -> prints "2" print(pdct.at_pos.keys[1]) # -> prints "y" print(list(pdct.at_pos.items[2])) # -> prints "[('x', 1), ('y', 2)]"
Vectorized access
Several functions support accessing member elements using vectors, for example:
Setting elements:
from cdxcore.pretty import PrettyObject r = PrettyObject() r['a','b'] = 1,2 print(r.a,r.b) # -> 1,2 r['a','b'] = (1,2) print(r.a,r.b) # -> 1,2
Reading elements:
r = PrettyObject(a=1,b=2) a, b = r['a','b'] print(a,b) # -> 1,2
Reading elements with defaults, classic method:
r = PrettyObject(a=1,b=2) a, b, c = r.get([‘a’,’b’,’c’],[1,2,33]) print(a,b,c) # -> 1,2,33
Reading elements with defaults, keyword methd
r = PrettyObject(a=1,b=2) a, b, c = r.get(a=11,b=22,c=33) print(a,b,c) # -> 1,2,33
Popping elements with defaults, keyword methd
r = PrettyObject(a=1,b=2) a, b, c = r.pop(a=11,b=22,c=33) print(a,b,c) # -> 1,2,33 assert len(r)==0
Same for
cdxcore.pretty.PrettyObject.setdefault():r = PrettyObject(a=1,b=2) a, b, c = r.setdefault(a=1,b=2,c=33) print(a,b,c) # -> 1,2,33 print(r.c) # -> 33
Assigning Member Functions
PrettyObjectobjects also allow assigning bona fide member functions by a simple semantic of the form:pdct = PrettyObject(b=2) pdct.mult_b = lambda self, x: self.b*x pdct.mult_b(3) # -> 6
Calling
pdct.mult_b(3)with abovepdctwill return 6 as expected. To assign static member functions, use the[]operator. The reason for this is as follows: consider:def mult( a, b ): return a*b pdct = PrettyObject() pdct.mult = mult pdct.mult(3,4) --> produces am error as three arguments must be passed: self, 3, and 4
In this case, use:
pdct = PrettyObject() pdct['mult'] = mult pdct.mult(3,4) --> 12
You can also pass member functions to the constructor:
p = PrettyObject( f=lambda self, x: self.y*x, y=2) p.f(3) # -> 6
Operators
Objects of type
cdxcore.pretty.PrettyObjectsupport the following operators:Comparison operator
==and!=test for equality of keys and values. Unlike for dictionaries comparisons are performed in in order. That meansPrettyObject(x=1,y=2)andPrettyObject(y=2,x=1)are not equal.Super/subset operators
>=and<=test for a super/sup set relationship, respectively.The
a | breturns the union of twocdxcore.pretty.PrettyObject. Elements of theboverwrite any elements ofa, if they are present in both. The order of the new dictionary is determined by the order of appearance of keys in firstaand thenb, that means in all but trivial casesa|b != b|a.The
|=operator is a short-cut forcdxcore.pretty.PrettyObject.update().
- Parameters:
- copyMapping, optional
If present, assign elements of
copytoself.- ** kwargs:
Key/value pairs to be added to
self.
- as_field()[source]#
This function provides support for
dataclasses.dataclassfields withPrettyObjectdefault values.When adding a field with a non-frozen default value to a
@dataclassclass, adefault_factoryhas to be provided. The functionas_fieldreturns the correspondingdataclasses.Fieldelement by returning simply:def factory(): return self return dataclasses.field( default_factory=factory )
Usage is as follows:
from dataclasses import dataclass @dataclass class A: data : PrettyDict = PrettyDict(x=2).as_field() a = A() print(a.data.x) # -> "2" a = A(data=PrettyDict(x=3)) print(a.data.x) # -> "3"
- property at_pos#
Elementary access to the data contained in
selfby ordinal position. The ordinal position of an element is determined by the order of addition to the dictionary.at_pos[position]returns an element or elements at an ordinal position:It returns a single element if
positionrefers to only one field.If
positionis a slice then the respecitve list of fields is returned.
at_pos.keys[position]returns the key or keys atposition.at_pos.items[position]returns the tuple(key, element)or a list thereof forposition.
You can also write data using the attribute notation:
at_pos[position] = itemassigns an item to an ordinal position:If
positionrefers to a single element,itemmust be the value to be assigned to this element.If
positionis a slice then ‘itemmust resolve to a list (or generator) of the required size.
- get(__key__=None, default=<cdxcore.pretty.PrettyObject._No_Default_dummy object>, **keys)[source]#
Get element
keywith optional defaultdefault. Equivalent todict.get(). Alternatively, this function takes a list of keys and their default values in dictionary notation in which case the read values are returned in order. You cannot mix usingkeyandkeys.Standard usage
This function supports
keybeing a sequence in which case this function returns a tuple of the same length with the respective results. Thedefaultvalue will be interpreted accordingly.Hence, the following works:
from cdxcore.pretty import PrettyObject r = PrettyObject(a=1, b=2) a,b,c = r.get( ['a', 'b','c'],[11,22,33] ) print(a,b,c) # -> 1,2,33
Keyword usage
Provide keys with default values, i.e.:
from cdxcore.pretty import PrettyObject r = PrettyObject(a=1, b=2) a,b,c = r.get( a=11, b=22, c=33 ) print(a,b,c) # -> 1,2,33
- items()[source]#
Equivalent to
dict.items()
- keys()[source]#
Equivalent to
dict.keys()
- no_default = <cdxcore.pretty.PrettyObject._No_Default_dummy object>#
- pop(__key__=None, default=<cdxcore.pretty.PrettyObject._No_Default_dummy object>, **keys)[source]#
Get and remove element
keywith optional defaultdefault. Equivalent todict.pop(). Alternatively, this function takes a list of keys and their default values in dictionary notation in which case the read values are returned in order. You cannot mix usingkeyandkeys.Standard usage
This function supports
keybeing a sequence in which case this function returns a tuple of the same length with the respective results. Thedefaultvalue will be interpreted accordingly.Hence, the following works:
from cdxcore.pretty import PrettyObject r = PrettyObject(a=1, b=2) a,b,c = r.pop( ['a', 'b','c'],[11,22,33] ) print(a,b,c) # -> 1,2,33
Keyword usage
Provide keys with default values, i.e.:
from cdxcore.pretty import PrettyObject r = PrettyObject(a=1, b=2) a,b,c = r.pop( a=11, b=22, c=33 ) print(a,b,c) # -> 1,2,33
- setdefault(__key__=None, default=None, **keys)[source]#
Returns the value for
keyordefaultif not found. In the latter case it addsdefaultas value forkeyto the dictionary. Equivalent todict.setdefault().Alternatively, this function takes a list of keys and their default values in dictionary notation in which case the read values are returned in order. You cannot mix using
keyandkeys.Standard usage
This function supports
keybeing a sequence in which case this function returns a tuple of the same length with the respective results. Thedefaultvalue will be interpreted accordingly.Hence, the following works:
from cdxcore.pretty import PrettyObject r = PrettyObject(a=1, b=2) a,b,c = r.setdefault( ['a', 'b','c'],[11,22,33] ) print(a,b,c) # -> 1,2,33 print(r.c) # -> 33
Keyword usage
Provide keys with default values, i.e.:
from cdxcore.pretty import PrettyObject r = PrettyObject(a=1, b=2) a,b,c = r.setdefault( a=11, b=22, c=33 ) print(a,b,c) # -> 1,2,33 print(r.c) # -> 33
- update(other=None, **kwargs)[source]#
Equivalent to
dict.update().Note that functon assignments are handled in normal dictionary fashion - in particular, bound functions will not become magically unbound.
- values()[source]#
Equivalent to
dict.values()