Metaprogramming

Autoname

Access an object’s name as a property

Autoname is a data-descriptor, which automatically looks up the name under which the object on which the descriptor is accessed is known by.

Import the descriptor using from mtoolbox.autoname import Autoname.

Example

>>> class Object(object):
...     name = Autoname()
>>> o = Object()
>>> o.name
'o'

By default Autoname will return the outer-most name that was defined for the object:

>>> class Object(object):
...     name = Autoname()
>>> def func(anobject):
...     return anobject.name
>>> o = Object()
>>> func(Object())
'anobject'
>>>
>>> g = o
>>> g.name
'o'
>>> del o
>>> g.name
'g'

You can change this behaviour by using the ‘first’ keyword:

>>> class Object(object):
...     name = Autoname(first=True)
>>> o = Object()
>>> o.name
'o'
>>> g = o
>>> g.name
'g'
>>> o.name
'g'

Note

Please be aware, that getting the inner-most name, is not what you want in most cases:

>>> class Object(object):
...     name = Autoname(first=True)
...     def printname(self):
...         print(self.name)
>>> o = Object()
>>> o.printname()
self
class mtoolbox.autoname.Autoname(initval=True, first=False)[source]

Bases: object

Create a new Autoname descriptor

Parameters:
  • initval (str, bool, None) – The initial name
  • first (bool) – Return the first found name of the object (or not)
Returns:

An Autoname instance

Return type:

Autoname

__get__(theobject, objtype)[source]

Return the name of theobject or None

Returns:the name of the object
Return type:str or None

Usage:

>>> class Object(object):
...     name = Autoname(first=True)
>>> obj = Object()
>>> obj.name
'obj'
>>> obj.name = 'another name'
>>> obj.name
'another name'
__set__(theobject, val)[source]

Set the name of the theobject

Parameters:
  • theobject (object) – The object to which’s class the descriptor is attached to
  • val (str, bool or None) – Sets the name to depending on the type: str sets the name to this str. False or None sets the name to None. True sets the name to automatically lookup.
Returns:

None

Raises:

TypeError if type(val) is invalid

Usage:
>>> class Object(object):
...     name = Autoname()
>>> o = Object()
>>> o.name = 'k'
>>> o.name
'k'
>>> o.name = True
>>> o.name
'o'
>>> o.name = False
>>> str(o.name)
'None'
>>> o.name = 4
Traceback (most recent call last):
...
TypeError: Autoname must be set to str, bool, NoneType

ILists

Module to provide an ‘intelligent’ list class

The IList class translates attribute access to the items it holds:

l.<name> == IList([obj.<name> for obj in l])

Import the IList class using from mtoolbox.ilist import IList.

Example

>>> l = IList([complex(3, 4), complex(6)])
>>> l.real
[3.0, 6.0]

You can also use callable attributes of your objects:

>>> l = IList([complex(3, 4), complex(6)])
>>> l
[(3+4j), (6+0j)]
>>> l.conjugate()
[(3-4j), (6-0j)]

You can add callbacks, for appending and removing objects. These callbacks must accept two positional arguments - the list and the object. The callbacks are called _after_ executing append or remove:

>>> def on_append(l, x):
...     print("Adding %s to %s." % (x, l))
>>> def on_remove(l, x):
...     print("Removing %s from %s." % (x, l))
>>> l = IList(on_append=on_append, on_remove=on_remove)
>>> l.append(3)
Adding 3 to [3].
>>> l.remove(3)
Removing 3 from [].
>>> def invalid_callback(l):
...     print(l)
>>> l = IList(on_append=invalid_callback)
Traceback (most recent call last):
...
TypeError: on_append and on_remove must accept 2 positional arguments
>>> l = IList(on_append=3)
Traceback (most recent call last):
...
TypeError: on_append and on_remove must accept 2 positional arguments
>>> def valid_callback(l=[], x=5):
...     pass
>>> def valid_callback2(l, x=5, y=3):
...     pass
>>> l = IList(on_append=valid_callback, on_remove=valid_callback2)

Be aware, that only attribute names, that are not used by the list class are overwritten, so if list implemented a attribute name, you can’t use it in this way. The following code doesn’t work, because list implements ‘__add__’ (so the result is NOT [4, 5] as one could expect):

>>> l = IList([1, 2])
>>> l + 3
Traceback (most recent call last):
...
TypeError: can only concatenate list (not "int") to list

If you wish to access attributes with these names, you can use IList.getattr() (see method documentation).

You can also apply any function to the items of an IList by calling IList.apply() (see method documentation).

class mtoolbox.ilist.IList(iterable=None, on_append=None, on_remove=None)[source]

Bases: list

‘intelligent’ list object

Parameters:
  • iterable (iterable) – The
  • on_append (callable) – callback(list, item) for append()
  • on_remove (callable) – callback(list, item) for remove()
Returns:

An IList instance

Return type:

IList

Note

Both callbacks must accept two positional arguments

append(obj)[source]

Add obj to IList

Parameters:obj (object) – object to append to list
Returns:None
Usage:
>>> l = IList()
>>> l
[]
>>> l.append(3)
>>> l
[3]
apply(func, *args, **kwargs)[source]

Apply func to the items of this IList

Parameters:
  • func (callable) – function to apply to this IList’s items
  • args (iterable) – additional arguments for func
  • kwargs (dict) – additional keyword arguments for func
Returns:

An IList instance

Return type:

IList

Usage:
>>> def f(x, pow=2):
...     return x**pow
>>> l = IList([0, 1, 2, 3, 4, 5])
>>> l.apply(f, pow=3)
[0, 1, 8, 27, 64, 125]
getattr(name)[source]
Parameters:name (str) – name of the items attributes to access
Returns:An IList instance
Return type:IList
Usage:
>>> l = IList([3, 5, 4])
>>> l.getattr('__add__')(2)
[5, 7, 6]
remove(obj)[source]

Remove obj from IList

Parameters:obj (object) – object to remove from list
Returns:None
Usage:
>>> l = IList([8])
>>> l
[8]
>>> l.remove(8)
>>> l
[]
>>> l.remove(6)
Traceback (most recent call last):
...
ValueError: list.remove(x): x not in list