1

いくつかの特性を持つネットワーク プロファイルをカプセル化するオブジェクトがあります。たとえば、私のプロファイルには接続があり、それに応じて、 IPオプション ( staticまたはdhcp )を持つことができる場合とできない場合があります。

したがって、私の最初の試みは、dictから拡張され、いくつかのヘルパー関数を追加する通常のクラスを使用することでした。

class Profile(dict):
    IP_CONNECTIONS = ('ethernet', 'wireless', 'pppoe')
    def is_ethernet(self): return self['Connection'] == 'ethernet'
    def is_wireless(self): return self['Connection'] == 'wireless'
    def is_wireless_adhoc(self): return self.is_wireless() and 'AdHoc' in self
    def has_ip(self)
        return self['Connection'] in self.IP_CONNECTIONS
    def has_ip_static(self)
        if not self.has_ip():
            return False
        if self.is_ipv4():
            return self['IP'] == 'static'
        if self.is_ipv6():
            return self['IP6'] == 'static'
        return False
    def has_ip_dhcp(self):
        if not self.has_ip():
            return False
        if self.is_ipv4():
            return self['IP'] == 'dhcp'
        if self.is_ipv6():
            return self['IP6'] == 'dhcp' or self['IP6'] == 'dhcp-noaddr'
        return False
    def is_ipv4(self): return self.has_ip() and 'IP' in self
    def is_ipv6(self): return self.has_ip() and 'IP6' in self
    def get_client(self):
        if self.has_ip_dhcp() and 'DHCPClient' in self:
            return self['DHCPClient']
        return None

これは機能しましたが、多くの特徴的な機能を備えた巨大なクラスがありましis_*has_*。それらのほとんどは、非常に特定のプロファイルにのみ使用され、Falseほとんどの場合返されます。

それから、継承を使用して特性を記述できることが頭に浮かびました。

__new__メソッドが呼び出されたときにデータがまだ利用できなかったため、メタクラスを実装しようとして失敗した後。私はこのようなものを思いついた:

def load_profile(filename):
    data = _read_profile(filename)
    bases = _classify_profile(data)
    baseclass = type('Profile', bases, {})
    return baseclass(data)

class IP:
    CONNECTIONS = ('ethernet', 'wireless')
class IPv4(IP):
    def is_static(self):
        return self['IP'] == 'static'
class IPv6(IP):
    def is_static(self):
        return self['IP6'] == 'static'
class DHCP:
    def get_client(self):
        return self['DHCPClient'] if 'DHCPClient' in self else None

class Wireless:
    def is_adhoc(self):
        return 'AdHoc' in self

def _classify_profile(data):
    classes = [dict]

    if data['Connection'] == 'wireless':
        classes.append(Wireless)
    if data['Connection'] in IP.CONNECTIONS:
        if 'IP' in data:
            classes.append(IPv4)
            if data['IP'] == 'dhcp':
                classes.append(DHCP)
        if 'IP6' in data:
            classes.append(IPv6)
            if data['IP6'] == 'dhcp' or data['IP6'] == 'dhcp-noaddr':
                classes.append(DHCP)

    return tuple(classes)

以前は をしていましたがprofile.has_ip()、今は でテストするだけisinstance(profile, IP)です。これは、責任を適切に分離することで、より明確に思えます。

質問: これは動的継承を実装する良い方法ですか? これを行うpythonicの方法は何でしょうか?

前もって感謝します!

4

1 に答える 1

0

動的継承の意味がよくわかりませんが、次のように書きます。

base_classes = []

class IP(dict):
    CONNECTIONS = ('ethernet', 'wireless')
    def is_static(self):
        raise NotImplementedError('To be implemented in subclasses.') 
    @classmethod
    def wants_the_meaningful_named_data(cls, data):
        return False
base_classes.append(IP)

class IPv4(IP):
    def is_static(self):
        return self['IP'] == 'static'
    @classmethod
    def wants_the_meaningful_named_data(cls, data):
        return data['Connection'] in cls.CONNECTIONS and 'IP' in data
base_classes.append(IPv4)

class IPv6(IP):
    def is_static(self):
        return self['IP6'] == 'static'
    @classmethod
    def wants_the_meaningful_named_data(cls, data):
        return data['Connection'] in cls.CONNECTIONS and 'IP6' in data
base_classes.append(IPv6)

def load_profile(filename):
    data = _read_profile(filename)
    for base_class in base_classes:
        if base_class.wants_the_meaningful_named_data(data):
            return base_class(data)
    return dict(data)

このようなものは私が好きなものでしょう。メタクラスに入る必要はないと思います。

于 2013-10-08T19:04:13.310 に答える