[Python-Dev] PEP 3144: IP Address Manipulation Library for the Python Standard Library (original) (raw)

"Martin v. Löwis" martin at v.loewis.de
Wed Aug 26 20:35:21 CEST 2009


netaddr employs a simple variant of the GoF Strategy design pattern (with added Python sensibility). It would be nice if you could avoid employing this kind of acronyms without explaining them. Not everybody drinks the design pattern kool-aid. (Google tells me that GoF seems to mean "Gang of Four", which is of course as meaningful as a hip-hop band name can be :-)) In any case, if you think netaddr's implementation strategy is better than ipaddr's, a detailed comparison would be welcome.

Just in case it still isn't clear "Strategy" above doesn't refer to "implementation strategy" (i.e. "way of implementing things").

Instead, "Strategy" is a specific design pattern, originally defined by one of Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides.

See

http://en.wikipedia.org/wiki/Strategy_pattern

for a detailed description. The basic idea is that you can switch algorithms at run-time, by merely replacing one object with another.

To use it, you define an abstract base class with a method called "execute". You then create as many subclasses as you want, redefining "execute" to provide specific strategies. You create a (often global) variable pointing to one instance of the base class, and dynamically assign this variable with an instance of the appropriate strategy class. Users of the strategy don't need to know what strategy is chosen.

The wikipedia article points (IMO correctly) out that the Strategy pattern is mostly useless in languages that have true function pointers, such as Python. You can still have the global variable part, but you don't need the abstract base class part at all.

In the specific case of netaddr, I think David is referring to the netaddr.strategy package, which has modules called ipv4 and ipv6, both implementing functions like valid_str and str_to_arpa. Then, class IPAddress has a method reverse_dns, which is defined as

def reverse_dns(self):
    """The reverse DNS lookup record for this IP address"""
    return self._module.int_to_arpa(self._value)

So IPv4 addresses and IPv6 addresses share the same class, but instances have different values of _module. IPAddress.init looks at the version keyword parameter if given, otherwise, it tries str_to_int first for v4, then for v6.

Whether that's better or not than using subclasses, I don't know.

Regards, Martin



More information about the Python-Dev mailing list