Warning when new attributes are added to classes at run time

Nick Vatamaniuc vatamane at gmail.com
Thu Jul 20 13:39:12 EDT 2006


Use __slots__ they will simply give you an error. But at the same time
I don't think they are inheritable and in general you should only use
slots for performance reasons (even then test before using).

Or you could also simulate a __slots__ mechanism the way you are doing
i.e. checking the attributes yourself. But I would suggest though that
you create a test case (unittest) and run testing _separately_ from
your code. Your code should do only what it does, too many  "if i
messed: up warn me" or "need to make sure I don't have extra
attributes" checks would make the code itself incomprehnsible over time
as half of it would end up being just checks for exceptional
situations. So spend 5 minutes to look up
http://pyunit.sourceforge.net/ and then in the long run your effort to
implement testing will be rewarded.

Nick V.



Matthew Wilson wrote:
> I sometimes inadvertently create a new attribute on an object rather
> update a value bound to an existing attribute.  For example:
>
>     In [5]: class some_class(object):
>        ...:      def __init__(self, a=None):
>        ...:          self.a = a
>        ...:
>
>     In [6]: c = some_class(a=1)
>
>     In [7]: c.a
>     Out[7]: 1
>
>     In [8]: c.A = 2
>
> I meant to update c.a but I created a new c.A.  I make this mistake
> probably hourly.
>
> I suspect adding attributes at run time can be a beautiful thing, but in
> this particular instance, I'm only using this feature to hurt myself.
>
> I wrote a simple class that will warn me when I make this mistake in the
> future:
>
>     import warnings
>
>     class C(object):
>
>         warn_on_new_attributes = True
>
>         standard_attributes = []
>
>         def __setattr__(self, name, value):
>
>             if self.warn_on_new_attributes \
>                 and name is not 'warn_on_new_attributes' \
>                 and name not in self.standard_attributes:
>
>                 warnings.warn("%s has no standard attribute %s."
>                               % (self.__class__.__name__, name))
>
>
>             self.__dict__[name] = value
>
>
>     class C1(C):
>
>         standard_attributes = ['a1', 'a2']
>
>
>     class C2(C):
>
>         warn_on_new_attributes = False
>
>     # Do some simple testing.
>     c11 = C1()
>     c11.a1 = 1
>     c11.a2 = 2
>     c11.a3 = 3
>     c11.a4 = 4
>
>     # Disable warnings for this instance.
>     c12 = C1()
>     c12.warn_on_new_attributes = False
>     c12.a1 = 1
>     c12.a2 = 2
>     c12.a3 = 3
>     c12.a4 = 4
>
>     c11.a5 = 5
>
>     # Use an object that has warnings disabled by default.
>     c2 = C2()
>     c2.a1 = 1
>     c2.a2 = 2
>     c2.a3 = 3
>     c2.a4 = 4
>
>     # enable warnings for this object.
>     c2.warn_on_new_attributes = True
>     c2.a1 = 1
>     c2.a5 = 5
>
>
> All comments are welcome.  Is there a better way of implementing the
> above class, OR, is this approach generally wrong-headed?  Am I the only
> one that makes this mistake?
>
> TIA
>
> --
> A better way of running series of SAS programs:
> http://overlook.homelinux.net/wilsonwiki/SasAndMakefiles




More information about the Python-list mailing list