Properties and Objects...

  • Thread starter George V. Neville-Neil
  • Start date
G

George V. Neville-Neil

I have been reading the mailing list and I am unfortunately going to
open up discussion I've seen twice in the last two years but which
still bugs me, so please accept my apologies in advance.

I have been working on a set of modules that make objects which look
like network packets (http://pcs.sf.net) in that you can set up a
class, say ipv4, which when instantiated has the following properties:

Note that setting the ttl in the packet changes the underlying bytes.
Doing this makes writing network tests, and other networking code,
extremely easy.

This is done by having Field classes which are collected into a list
in a Packet class (the layout) and by doing special setattr/getattr
calls.

I have been trying to switch this over to using properties, which seem
at first glance to be cleaner, but which I am having a lot of problems
with. In particular I want to add a property to an object, not a
class. The field list in a class is actually relatively static but I
wind up with ugly code like:

class ethernet(pcs.Packet):
"""Ethernet"""
__layout__ = pcs.Layout()
_map = ethernet_map.map

src = pcs.StringField("src", 48)
dst = pcs.StringField("dst", 48)
type = pcs.Field("type", 16)

def __init__(self, bytes = None, timestamp = None):
"""initialize an ethernet packet"""

src = pcs.StringField("src", 48)
dst = pcs.StringField("dst", 48)
type = pcs.Field("type", 16)

pcs.Packet.__init__(self, [dst, src, type], bytes = bytes)
self.description = inspect.getdoc(self)

and assigning the properties at class time means that it's hard to
have variations, packets with the same name but with slightly varying
field lists.

So, is there a way to assign a property to an object, like this:

def __init__(....
self.src = property()

or something like that?

And, failing that, is there a clean way to modify the class in it's
__init__() method so I don't have to call the Field objects twice,
once for the property effect and once to put into the list in the base
Packet class?

With my somewhat convoluted setattr/getattr implementation the
Ethernet class looked like this:

class ethernet(pcs.Packet):
"""Ethernet"""
__layout__ = pcs.Layout()
_map = ethernet_map.map

def __init__(self, bytes = None, timestamp = None):
"""initialize an ethernet packet"""

src = pcs.StringField("src", 48)
dst = pcs.StringField("dst", 48)
type = pcs.Field("type", 16)

pcs.Packet.__init__(self, [dst, src, type], bytes = bytes)
self.description = inspect.getdoc(self)

which was much more straightforward for someone to understand and to
code. Since one of the project goals is to have the creation of new
packets classes be as easy as possible I would like to be able to do
something closer to the above.

Best,
George
 
P

Peter Otten

George said:
I have been trying to switch this over to using properties, which seem
at first glance to be cleaner, but which I am having a lot of problems
with. In particular I want to add a property to an object, not a
class.

You can't. The underlying mechanism (descriptors) works on the class level.
The field list in a class is actually relatively static but I
wind up with ugly code like:

class ethernet(pcs.Packet):
"""Ethernet"""
__layout__ = pcs.Layout()
_map = ethernet_map.map

src = pcs.StringField("src", 48)
dst = pcs.StringField("dst", 48)
type = pcs.Field("type", 16)

From the piece of code you present I would guess that the above class
attributes are superfluous. Or doesn't pcs.Packet.__init__() do the

self.src = ...

thingy?
def __init__(self, bytes = None, timestamp = None):
"""initialize an ethernet packet"""

src = pcs.StringField("src", 48)
dst = pcs.StringField("dst", 48)
type = pcs.Field("type", 16)

pcs.Packet.__init__(self, [dst, src, type], bytes = bytes)
self.description = inspect.getdoc(self)

and assigning the properties at class time means that it's hard to have
variations, packets with the same name but with slightly varying field
lists.

What's so hard about subclassing?
So, is there a way to assign a property to an object, like this:

def __init__(....
self.src = property()

or something like that?

You can make a property that delegates its behaviour, e. g:

import new

def get_src_one(self):
return 42

class A(object):
src = property(lambda self: self.get_src())
def __init__(self, get):
self.get_src = new.instancemethod(get, self)

a = A(get_src_one)
print a.src

But -- ceterum censeo -- subclassing is probably better, cleaner and
faster. Then instead of calling the class directly make a factory function
that picks the appropriate subclass.

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top