Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Edit:</strong> My previous answer tried to make a generalized AutoProperties metaclass which I hoped could be of general use. As @martineau's answer shows a solution specialized to the <code>Vector</code> class can make things simpler. </p> <p>Here's another idea along those lines (specialized simplicity over generalized complexity). It uses a class decorator (which I think is slightly simpler to understand than a metaclass) and @martineau's idea of simplifying the getters and setters with default values: </p> <pre><code>def AutoProperties(*props): def _AutoProperties(cls): for attr in props: def getter(self,_attr='_'+attr): return getattr(self, _attr) def setter(self, value, _attr='_'+attr): setattr(self, _attr, float(value)) setattr(cls,attr,property(getter,setter)) return cls return _AutoProperties @AutoProperties('x','y','z') class Vector(object): '''Creates a Maya vector/triple, having x, y and z coordinates as float values''' def __init__(self, x=0, y=0, z=0): self._x, self._y, self._z = map(float,(x, y, z)) </code></pre> <p><strong>Original answer:</strong> Here is a way to avoid repeating boiler-plate code when defining many similar properties. </p> <p>I've tried to make the solution reasonably general, so it might be of use to people in other situations beside this particular one.</p> <p>To use it you need to do 2 things: <OL> <LI>Put</p> <pre><code> __metaclass__=AutoProperties(('x','y','z')) </code></pre> <p>at the beginning of the definition of your class. You can list (as strings) as many attributes (e.g. <code>x</code>,<code>y</code>,<code>z</code>) as you wish. <code>AutoProperties</code> will turn them into properties.</p> <p><LI>Your class, e.g. <code>Vector</code>, needs to define staticmethods <code>_auto_setter</code> and <code>_auto_getter</code>. They take one argument, the attribute name as a string, and return the setter or getter function, respectively, for that attribute. </OL></p> <p>The idea of using metaclasses to automatically set up properties comes from Guido Rossum's essay on <a href="http://www.python.org/download/releases/2.2.3/descrintro/#metaclasses" rel="nofollow noreferrer">properties and metaclasses</a>. There he defines an <code>autoprop</code> metaclass similar to what I use below. The main difference is that <code>AutoProperties</code> expects the user to define getter and setter <em>factories</em> instead of manually defined getters and setters.</p> <pre><code>def AutoProperties(props): class _AutoProperties(type): # Inspired by autoprop (http://www.python.org/download/releases/2.2.3/descrintro/) def __init__(cls, name, bases, cdict): super(_AutoProperties, cls).__init__(name, bases, cdict) for attr in props: fget=cls._auto_getter(attr) fset=cls._auto_setter(attr) setattr(cls,attr,property(fget,fset)) return _AutoProperties class Vector(object): '''Creates a Maya vector/triple, having x, y and z coordinates as float values''' __metaclass__=AutoProperties(('x','y','z')) def __init__(self, x=0, y=0, z=0): # I assume you want the initial values to be converted to floats too. self._x, self._y, self._z = map(float,(x, y, z)) @staticmethod def _auto_setter(attr): def set_float(self, value): setattr(self, '_'+attr, float(value)) return set_float @staticmethod def _auto_getter(attr): def get_float(self): return getattr(self, '_'+attr) return get_float if __name__=='__main__': v=Vector(1,2,3) print(v.x) # 1.0 v.x=4 print(v.x) # 4.0 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload