Dividiendo las propiedades de Python en categorías

I have a class which contains a large amount of properties. More specifically, the class represents my router. I want to divide its properties to categories, meaning that in order to retrieve the LAN ip and the WAN ip I would not have to type:

router.wan_ip
router.lan_ip

But instead type:

router.wan.ip
router.lan.ip

The properties are dynamic and retrieved when calling their functions. My current implementation:

class Category(object):
    def __init__(self, parent):
        self._parent = parent

class Lan(Category):
    @property
    def ip(self):
        self._parent._get_property("lanip")

class Wan(Category):
    @property
    def ip(self):
        self._parent._get_property("wanip")

class Router(object):
    def __init__(self, ):
        self.lan = Lan(self)
        self.wan = Wan(self)

    def _get_property(self, property_name):
        # Some code here

But I wounder if there is a better way

preguntado el 30 de junio de 12 a las 15:06

What is wrong with what you have? What specifically would make an alternate solution "better"? -

I think that the two-way relationship between the categories and the parent class, which is made by giving the categories the instance of their parent, is not such a good OOP practice. Am I wrong? -

_get_property should not exist. Just use regular Python properties and __getattr__ para eso. -

Your solution is simple and obvious, doesn't require any advanced knowledge, and does meet your requirements. In which way do you think it could be "better" ? The only point is that you have a circular reference that may keep your Router instances alive for longer than strictly required, which may or not be a problem depending on client code and execution context. -

Also, personally, if the Router object is going to be the one storing the property values, I'd stick with the underscores. I'm not sure what value you gain by overengineering this. (Alternately, have Wan y Lan store the property values, and work around Router not having them all.) -

3 Respuestas

You are probably overthinking this structure, but if you want objects...

Wan y Lan should not exist. You can pass a prefix for the Category class so it will search for ...ip. Las _get_property method could be replaced by a dictionary. If you need to calculate the values on the fly, you may create a dict with functions to be called.

class Category(object):
    def __init__(self, parent, prefix):
        self.parent = parent
        self.prefix = prefix
    @property
    def ip(self):
        self.parent.data[self.prefix + "ip"]

class Router(object):
    def __init__(self, data):
        self.lan = Category(self, 'lan')
        self.wan = Category(self, 'wan')
        self.data = data

By the way, this program doesn't need to have any class at all. Seems like you just need dictionaries. You can create a function to build these dictionaries if needed

router = {'wan': {'ip': '1.2.3.4'}, 'lan': {'ip': '2.3.4.5'}}

Respondido el 30 de junio de 12 a las 16:06

Having Lan and Wan as classes allow to have categories with different attributes set - some "categories" may not have an "ip" property, and may have properties that makes no sense for a Wan or Lan. - bruno desthuilliers

@brunodesthuilliers Then make a soltero subclase de Category for those. That's the point - bernardo

Puedes usar __getattr__ that will allow you to access properties that don't really exist by that name, by examining the name of the property, and mapping it to an actual property.

Respondido el 30 de junio de 12 a las 16:06

Having properties that do "exist by that name" makes introspection easier so better to use descriptors than __getattr__ whenever possible. Also, using __getattr__ in this case would require to return category instances since "router.wan.id" would resolve to router.__getattr__('wan').__getattr__('id'). - bruno desthuilliers

I think you could use descriptors [1] for an unique Category class.

[ XNMUX ] http://docs.python.org/reference/datamodel.html#descriptors

Respondido 01 Jul 12, 03:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.