Trying to learn about metaclasses
Chris Kaynor
ckaynor at zindagigames.com
Mon Jul 25 13:53:48 EDT 2011
On Mon, Jul 25, 2011 at 8:36 AM, Steven W. Orr <steveo at syslang.net> wrote:
> I have been doing a lot of reading. I'm starting to get it. I think it's
> really cool as well as dangerous, but I plan on being respectful of the
> construct. I found a web page that I found quite readable.
>
> http://cleverdevil.org/**computing/78/<http://cleverdevil.org/computing/78/>
>
> So, I tried to run the example code (below), and I get AttributeError. If
> someone can get me over this hump, I'd be grateful. It complains that Person
> has no _fields attribute, but the print hello I have in EnforcerMeta doesn't
> happen either. Am I doing something wrong?
>
> I'm running python 2.6.2
>
> Here's the error:
>
> 585 > ./meta1.py
> Traceback (most recent call last):
> File "./meta1.py", line 38, in <module>
> swo.name = 'swo'
> File "./meta1.py", line 27, in __setattr__
> if key in self._fields:
> AttributeError: 'Person' object has no attribute '_fields'
>
>
> And here's the code:
>
> #! /usr/bin/python
> # http://cleverdevil.org/**computing/78/<http://cleverdevil.org/computing/78/>
> class Field(object):
> def __init__(self, ftype):
> self.ftype = ftype
>
> def is_valid(self, value):
> return isinstance(value, self.ftype)
>
> class EnforcerMeta(type):
> def __init(cls, name, bases, ns):
> # Store the field definitions on the class as a dictionary
> # mapping the field name to the Field instance.
> print 'Hello'
> cls._fields = {}
>
> # loop through the namespace looking for Field instances.
> for key, value in ns.items():
> if isinstance(value, Field):
> cls._fields[key] = value
>
> class Enforcer(object):
> # attach the metaclass
> __metaclass__ = EnforcerMeta
>
> def __setattr__(self, key, value):
> if key in self._fields:
> if not self._fields[key].is_valid(**value):
> raise TypeError('Invalid type for field.')
> super(Enforcer, self).__setattr__(key, value)
If I understand what you are trying to do here (other than playing with
metaclasses), you should be able to implement this as a descriptor (
http://docs.python.org/reference/datamodel.html#implementing-descriptors).
Something like (untested):
class Field(object):
def __init__(self, name, type):
self.ftype = type
self.name = name
def __get__(self, instance, owner):
return getattr(instance, self.name)
def __set__(self, instance, value):
if not self.is_valid(value):
raise TypeError()
setattr(instance, self.name, value)
def is_valid(self, value):
return isinstance(value, self.ftype)
>
> class Person(Enforcer):
> name = Field(str)
> age = Field(int)
>
> if __name__ == '__main__':
> swo = Person()
> swo.name = 'swo'
> print 'swo:', swo
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20110725/64dda2e6/attachment-0001.html>
More information about the Python-list
mailing list