473,461 Members | 1,799 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

decorator to prevent adding attributes to class?

After spending the morning debugging where I had misspelled the name of an
attribute (thus adding a new attr instead of updating an existing one), I
would like a way to decorate a class so that attributes cannot be (easily)
added.

I guess class decorators are not available yet (pep 3129), but probably
inheritance can be used.

Can anyone suggest an implementation?

Jul 11 '08 #1
5 4965
On Jul 11, 5:29*pm, Neal Becker <ndbeck...@gmail.comwrote:
After spending the morning debugging where I had misspelled the name of an
attribute (thus adding a new attr instead of updating an existing one), I
would like a way to decorate a class so that attributes cannot be (easily)
added.

I guess class decorators are not available yet (pep 3129), but probably
inheritance can be used.

Can anyone suggest an implementation?
This article could give you same idea (it is doing the opposite,
warning you
if an attribute is overridden):
http://stacktrace.it/articoli/2008/0...-con-i-mixin1/

There is also a recipe that does exactly what you want by means of a
metaclass:
http://aspn.activestate.com/ASPN/Coo.../Recipe/252158
It is so short I can write it down here:
# requires Python 2.2+

def frozen(set):
"Raise an error when trying to set an undeclared name."
def set_attr(self,name,value):
if hasattr(self,name):
set(self,name,value)
else:
raise AttributeError("You cannot add attributes to %s" %
self)
return set_attr

class Frozen(object):
"""Subclasses of Frozen are frozen, i.e. it is impossibile to add
new attributes to them and their instances."""
__setattr__=frozen(object.__setattr__)
class __metaclass__(type):
__setattr__=frozen(type.__setattr__)

Of course using frozen classes is not Pythonic at all, and I wrote the
recipe as
a proof of concept, not to use it.

Michele Simionato
Jul 11 '08 #2
Michele Simionato wrote:
This article could give you same idea (it is doing the opposite,
warning you
if an attribute is overridden):
http://stacktrace.it/articoli/2008/0...-con-i-mixin1/

There is also a recipe that does exactly what you want by means of a
metaclass:
http://aspn.activestate.com/ASPN/Coo.../Recipe/252158
It is so short I can write it down here:
# requires Python 2.2+

def frozen(set):
"Raise an error when trying to set an undeclared name."
def set_attr(self,name,value):
if hasattr(self,name):
set(self,name,value)
else:
raise AttributeError("You cannot add attributes to %s" %
self)
return set_attr

class Frozen(object):
"""Subclasses of Frozen are frozen, i.e. it is impossibile to add
new attributes to them and their instances."""
__setattr__=frozen(object.__setattr__)
class __metaclass__(type):
__setattr__=frozen(type.__setattr__)
I don't get it. Why use a metaclass? Wouldn't the following be the same,
but easier to grasp:

class Frozen(object):
def __setattr__(self, name, value):
if not hasattr(self, name):
raise AttributeError, "cannot add attributes to %s" % self
object.__setattr__(self, name, value)

Btw, the main drawback with Frozen is that it will not allow to set any
new attributes even inside __init__.
Some people would advise to use __slots__:
http://docs.python.org/ref/slots.html#l2h-222
Some other people would advise NOT to use __slots__:
http://groups.google.com/group/comp....2e859b9c002b28

Personally, if I must absolutely, I'd go for explicitely freeze the
object at the end of __init__:

class Freezeable(object):
def freeze(self):
self._frozen = None

def __setattr__(self, name, value):
if hasattr(self, '_frozen') and not hasattr(self, name):
raise AttributeError
object.__setattr__(self, name, value)
class Foo(Freezeable):
def __init__(self):
self.bar = 42
self.freeze() # ok, we set all variables, no more from here
x = Foo()
print x.bar
x.bar = -42
print x.bar
x.baz = "OMG! A typo!"
Cheers,
RB
Jul 11 '08 #3
On Jul 11, 6:38*pm, Robert Bossy
I don't get it. Why use a metaclass? Wouldn't the following be the same,
but easier to grasp:

class Frozen(object):
* * def __setattr__(self, name, value):
* * * *if not hasattr(self, name):
* * * * * raise AttributeError, "cannot add attributes to %s" %self
* * * *object.__setattr__(self, name, value)
This is easier, but it does not stop the user from
adding class level attributes: this is the job
of the metaclass. If you don't care about
class level attributes (including methods,
properties, etc) and you are content with restricting
only the instance attributes your recipe is fine, yes.
Jul 11 '08 #4
Robert Bossy wrote:
class Foo(Freezeable):
def __init__(self):
self.bar = 42
self.freeze() # ok, we set all variables, no more from here
x = Foo()
print x.bar
x.bar = -42
print x.bar
x.baz = "OMG! A typo!"
Pretty nice, but unfortunately the subclass has to remember to call freeze
in it's init. Too bad that can't be automated.
Jul 11 '08 #5
On Jul 11, 9:24*pm, Neal Becker <ndbeck...@gmail.comwrote:
Robert Bossy wrote:
class Foo(Freezeable):
def __init__(self):
self.bar = 42
self.freeze() # ok, we set all variables, no more from here
x = Foo()
print x.bar
x.bar = -42
print x.bar
x.baz = "OMG! A typo!"

Pretty nice, but unfortunately the subclass has to remember to call freeze
in it's init. *Too bad that can't be automated.
It can with a metaclass redefining the __call__ method
to call freeze after instantation. But there
would a lot of magic going on such a design.
Jul 12 '08 #6

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

Similar topics

14
by: Sandy Norton | last post by:
If we are going to be stuck with @decorators for 2.4, then how about using blocks and indentation to elminate repetition and increase readability: Example 1 --------- class Klass: def...
37
by: Bengt Richter | last post by:
ISTM that @limited_expression_producing_function @another def func(): pass is syntactic sugar for creating a hidden list of functions. (Using '|' in place of '@' doesn't change the picture...
5
by: Doug | last post by:
I am looking at using the decorator pattern to create a rudimentary stored proc generator but am unsure about something. For each class that identifies a part of the stored proc, what if I want to...
1
by: Doug | last post by:
I am looking at using the decorator pattern to create a rudimentary stored proc generator but am unsure about something. For each class that identifies a part of the stored proc, what if I want to...
4
by: Wilbert Berendsen | last post by:
Hi, is it possible to manipulate class attributes from within a decorator while the class is being defined? I want to register methods with some additional values in a class attribute. But I...
0
by: Christian Heimes | last post by:
Wilbert Berendsen schrieb: It's really tricky . The class object doesn't exists yet. It's created after all functions are parsed and created. You have can walk up the stack frames but it's ugly....
0
by: rbossy | last post by:
>class Foo(Freezeable): Not to mention that subclasses constructors could be bit, like that: class Foo(Freezeable): ... class Bar(Foo): def __init__(self, *args, **kw): Foo.__init__(self,...
14
by: Rafe | last post by:
Hi, I've encountered a problem which is making debugging less obvious than it should be. The @property decorator doesn't always raise exceptions. It seems like it is bound to the class but...
8
by: Bryan | last post by:
I want my business objects to be able to do this: class Person(base): def __init__(self): self.name = None @base.validator def validate_name(self): if not self.name: return
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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,...
1
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
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.