473,398 Members | 2,165 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

Warning when new attributes are added to classes at run time


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/wilson...asAndMakefiles
Jul 19 '06 #1
6 1206
Matthew Wilson wrote:
I sometimes inadvertently create a new attribute on an object rather
update a value bound to an existing attribute. For example:
<snippage>
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?
It's never been much a problem for me but you could look into __slots__

http://docs.python.org/ref/slots.html

....
jay

Jul 19 '06 #2
Matthew Wilson schrieb:
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.
Try pylint & pychecker.

Diez
Jul 19 '06 #3
Matthew Wilson wrote:
I sometimes inadvertently create a new attribute on an object rather
update a value bound to an existing attribute. For example:
(snip)
>
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.
See other posts in this thread for some other possible solutions.
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
Make it:
object.__setattr__(self, name, value)

Your approach will lead to strange results if you mix it with properties
or other descriptors...

class C1(C):

standard_attributes = ['a1', 'a2']
DRY violation here. And a potential problem with inheritance (as always
with class attributes).

(snip)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 20 '06 #4
On Thu 20 Jul 2006 04:32:28 AM EDT, Bruno Desthuilliers wrote:
> self.__dict__[name] = value
Make it:
object.__setattr__(self, name, value)

Your approach will lead to strange results if you mix it with properties
or other descriptors...
Thanks!
> class C1(C):

standard_attributes = ['a1', 'a2']

DRY violation here. And a potential problem with inheritance (as always
with class attributes).
Considering I had to look up what DRY meant before replying to this
message, I may be missing your point. Is the repeat here that each
subclass has to define its own list of standard attributes? Or, is it
that the standard_attributes list holds strings, but I could build that
list up by looking at my existing attributes?

If you're feeling charitable, can you explain what you mean a little
more?

TIA
--
A better way of running series of SAS programs:
http://overlook.homelinux.net/wilson...asAndMakefiles
Jul 20 '06 #5
Matthew Wilson wrote:
On Thu 20 Jul 2006 04:32:28 AM EDT, Bruno Desthuilliers wrote:
(snip)
>
>> class C1(C):

standard_attributes = ['a1', 'a2']

DRY violation here. And a potential problem with inheritance (as always
with class attributes).


Considering I had to look up what DRY meant before replying to this
message, I may be missing your point. Is the repeat here that each
subclass has to define its own list of standard attributes? Or, is it
that the standard_attributes list holds strings, but I could build that
list up by looking at my existing attributes?
Mostly the second. But now, how are you going to build that list from
"existing attributes" before these attributes exists ?-) (chicken and
egg problem here...)

FWIW, you could use custom descriptors to build the 'schema', then use a
metaclass to detect these descriptors and build the "allowed attributes"
list. But the whole thing seems overkill to me if it's only to solve
typo problems (can be interesting for other reasons...).

Re-read the three first answers to your post - unit-tests,
pylint/pychecker, eventually slots...

My 2 cents

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 20 '06 #6
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/wilson...asAndMakefiles
Jul 20 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

50
by: Dan Perl | last post by:
There is something with initializing mutable class attributes that I am struggling with. I'll use an example to explain: class Father: attr1=None # this is OK attr2= # this is wrong...
4
by: Adie | last post by:
Hi, I wonder if anyone might lend me a brain. I have a stock database to build that covers over 1000 products, which might be said to exist in around 50 product families. Obviously, just to be...
5
by: Robert A Riedel | last post by:
I have a class that is intended to be exported in a DLL that uses another class that is in a static library. All clients that use the DLL will also link with the same static library. In summary,...
2
by: Andrew Backer | last post by:
I have a series of class variables that are assigned to through reflection. Every time I compile one of these classes I get this warning : warning CS0649: Field 'xxx' is never assigned to, and...
18
by: JohnR | last post by:
From reading the documentation, this should be a relatively easy thing. I have an arraylist of custom class instances which I want to search with an"indexof" where I'm passing an instance if the...
2
by: Siemel Naran | last post by:
I keep getting warning messages like these: ....\include\myfile.h(451) : warning C4251: 'MyClass::m_myvariable' : class 'CPtrArray' needs to have dll-interface to be used by clients of class...
6
by: Bart Simpson | last post by:
I am writing a shared object (Dll in Windows) and I am making extensive use of the STL. I am getting lots of warnings like this: ClassA.h(139): warning C4251: 'ClassA::indexarray' : class...
5
by: holmescn | last post by:
what is the meaning of warning attributes ignored on template instantiation. i got it when i compiled stlport 5.1.3. anybody can help me ? thx!
2
by: Thelma Lubkin | last post by:
I use my own matrix and vector classes. I wrote them before such things were generally available and I've stuck with them ever since. I've just added an Octonion class derived from the vectors...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.