Python Snippets
- Daniel Stonier
Owned by Daniel Stonier
Idioms
Aliasing Class Methods
Allows you to add aliases to methods in a class.
Aliasing Decorators
class alias(object): """ Alias class that can be used as a decorator for making methods callable through other names (or "aliases"). Note: This decorator must be used inside an @aliased -decorated class. For example, if you want to make the method shout() be also callable as yell() and scream(), you can use alias like this: @alias('yell', 'scream') def shout(message): # .... """ def __init__(self, *aliases): """Constructor.""" self.aliases = set(aliases) def __call__(self, f): """ Method call wrapper. As this decorator has arguments, this method will only be called once as a part of the decoration process, receiving only one argument: the decorated function ('f'). As a result of this kind of decorator, this method must return the callable that will wrap the decorated function. """ f._aliases = self.aliases return f def aliased(aliased_class): """ Decorator function that *must* be used in combination with @alias decorator. This class will make the magic happen! @aliased classes will have their aliased method (via @alias) actually aliased. This method simply iterates over the member attributes of 'aliased_class' seeking for those which have an '_aliases' attribute and then defines new members in the class using those aliases as mere pointer functions to the original ones. Usage: @aliased class MyClass(object): @alias('coolMethod', 'myKinkyMethod') def boring_method(): # ... i = MyClass() i.coolMethod() # equivalent to i.myKinkyMethod() and i.boring_method() """ original_methods = aliased_class.__dict__.copy() for name, method in original_methods.iteritems(): if hasattr(method, '_aliases'): # Add the aliases for 'method', but don't override any # previously-defined attribute of 'aliased_class' for alias in method._aliases - set(original_methods): setattr(aliased_class, alias, method) return aliased_class # # A very simple example # @aliased class Vehicle(object): def __init__(self, brand, model, color): """Constructor.""" self.brand = brand self.model = model self.color = color @alias('modelBrandAndColor', 'getModelBrandAndColour', 'getDescription') def model_brand_and_color(self): """Get the model and brand of this Vehicle.""" return '{0} {1} {2}'.format(self.color, self.brand, self.model) vehicle = Vehicle('Chevrolet', 'Spark', 'black') # Now your API looks like your users would want. # Any of the following lines is equivalent to the others: print vehicle.model_brand_and_color() print vehicle.getDescription() print vehicle.modelBrandAndColor() print vehicle.getModelBrandAndColour()
Borg Idiom
A variant of the singleton pattern allowing instantiations that reference a single shared storage. Various construction methods are in this blog post. Some more interesting ideas are below:
Borg Class Decorator
def borg(cls): cls._state = {} orig_init = cls.__init__ def new_init(self, *args, **kwargs): self.__dict__ = cls._state orig_init(self, *args, **kwargs) cls.__init__ = new_init return cls # Allows you to write this: @borg class Foo(object): def say_hello(self): print "hello, I'm a borg"
Borg Idiom - A Blackboard of Blackboards
class Blackboard(defaultdict): """A dict that defaults values to None. Blackboards are registered by name. All blackboards with the same name have the same contents. """ _name_dict = defaultdict(dict) # For a twist on the Borg idiom def __init__(self, name, **kwargs): self.__dict__ = Blackboard._name_dict[name] default = lambda: None super(Blackboard, self).__init__(default, **kwargs)
Class Registry
Introspect on a base class to see what classes have inherited from it
Colour Class Registry
class RegisterLeafClasses(type): def __init__(cls, name, bases, nmspc): super(RegisterLeafClasses, cls).__init__(name, bases, nmspc) if not hasattr(cls, 'registry'): cls.registry = set() cls.registry.add(cls) cls.registry -= set(bases) # Remove base classes # Metamethods, called on class objects: def __iter__(cls): return iter(cls.registry) def __str__(cls): if cls in cls.registry: return cls.__name__ return cls.__name__ + ": " + ", ".join([sc.__name__ for sc in cls]) class Color(object): __metaclass__ = RegisterLeafClasses class Blue(Color): pass class Red(Color): pass class Green(Color): pass class Yellow(Color): pass print(Color) class PhthaloBlue(Blue): pass class CeruleanBlue(Blue): pass print(Color) for c in Color: # Iterate over subclasses print(c) class Shape(object): __metaclass__ = RegisterLeafClasses class Round(Shape): pass class Square(Shape): pass class Triangular(Shape): pass class Boxy(Shape): pass print(Shape) class Circle(Round): pass class Ellipse(Round): pass print(Shape) """ Output: Color: Red, Blue, Green, Yellow Color: Red, CeruleanBlue, Green, PhthaloBlue, Yellow Red CeruleanBlue Green PhthaloBlue Yellow Shape: Square, Round, Boxy, Triangular Shape: Square, Ellipse, Circle, Boxy, Triangular """
Tarballs - Strip Prefix and Extract
Aliasing Decorators
import tarfile def strip_leading_drake_prefix(tarball): prefix = "drake/" offset = len(prefix) for tarinfo in tarball.getmembers(): if tarinfo.name.startswith(prefix): tarinfo.name = tarinfo.name[offset:] yield tarinfo tarball = tarfile.open("/tmp/drake.tar.gz") tarball.extractall("/opt/drake", strip_leading_drake_prefix(tarball))