2011-11-20 3 views
2

아래의 코드에서 클래스에서 self.owner을 제거하는 방법을 찾으려고합니다 ... 아이디어는 주어진 VLAN에서 누가 IP 주소를 소유하고 있는지 알고 싶습니다. 또는 인터페이스를 명시 적으로 호출하지 않아도됩니다.효율적으로 파이썬 개체의 IP 주소 인스턴스 소유권을 조사합니다.

IPv4 주소의 소유자를 파생시키는 더 좋은 방법이 있습니까 (아마도 인트로 스펙 션을 통해)?

import ipaddr 

class SomethingOwned(object): 
    def __init__(self, owner=None): 
     self._owner = owner 
     # Build self.owner (the object instance that owns the subclass object) 
     self._create_owner() 

    def _create_owner(self): 
     """ 
     create self.owner and ensure the subclass was called correctly 
     """ 
     if not (self._owner is None): 
      self.owner = self._owner 
     else: 
      raise ValueError, "%s() must be called with an 'owner' arg, which cannot be None" % self.__class__.__name__ 

class L3Address(SomethingOwned): 
    """ 
    A Layer3 IP PDU address that has an owning object 
    """ 
    def __init__(self, version=None, owner=None, addr=None, masklen=None): 
     # Call SomethingOwned.__init__(owner=owner) to add an owner attribute 
     super(L3Address, self).__init__(owner=owner) 
     self._addr = addr 
     self._masklen = masklen 
     self._version = version 

     # Build self._obj 
     self._create_ip_object() 

     self.addr = self._obj.ip 
     self.netmask = self._obj.netmask 
     self.masklen = self._obj.prefixlen 

    def __repr__(self): 
     return "<IPv%i %s/%s>" % (self._version, self.addr, self.masklen) 


    def _create_ip_object(self): 
     """ 
     create self._obj and ensure the subclass was called with the correct version 
     """ 
     if self._version==4: 
      if (self._masklen is None): 
       self._obj = ipaddr.IPv4Network(self._addr) 
      else: 
       self._obj = ipaddr.IPv4Network("%s/%s" % (self._addr, self._masklen)) 
     elif version==6: 
      if (self._masklen is None): 
       self._obj = ipaddr.IPv6Network(self._addr) 
      else: 
       self._obj = ipaddr.IPv6Network("%s/%s" % (self._addr, self._masklen)) 
     else: 
      raise ValueError, "Version must be 4 or 6" 


class IPv4(L3Address): 
    def __init__(self, **kwargs): 
     ## Initialize the IPv4 network object instance 
     # Call L3Protocol.__init__(version=4 **kwargs) 
     super(IPv4, self).__init__(version=4, **kwargs) 

class IPv6(L3Address): 
    def __init__(self, **kwargs): 
     ## Initialize the IPv6 network object instance 
     # Call L3Protocol.__init__(version=6 **kwargs) 
     super(IPv4, self).__init__(version=6, **kwargs) 

class Vlan(object): 
    def __init__(self, name=None, id=None, ipv4=None): 
     self.id = id 
     self.name = name 
     if not (ipv4 is None): 
      ### NOTE: I am trying to eliminate the need for the owner arg here 
      self.ipv4 = IPv4(owner=self, addr=ipv4) 
    def __repr__(self): 
     return "Vlan %s (name: %s)" % (self.id, self.name) 

class Interface(object): 
    def __init__(self, id=None, ipv4=None): 
     self.id = id 
     self.ipv4 = None 
     if not (ipv4 is None): 
      ### NOTE: I am trying to eliminate the need for the owner arg here 
      self.ipv4 = IPv4(owner=self, addr=ipv4) 
    def __repr__(self): 
     return "Interface %s" % self.id 



if __name__=='__main__': 
    def find_owner(ip_instance): 
     print "Owner of '%s' is '%s'" % (ip_instance, ip_instance.owner) 

    find_owner(Interface(id='ge-0/0/0', ipv4='1.1.1.1').ipv4) 
    find_owner(Vlan(id='25', name='accounting', ipv4='1.1.1.2/25').ipv4) 

실행은 결과 :이 단지 L3Protocol에서 owner 필드를 제거 할 수있는 방법입니다 그냥 마술 런타임에 그것을 결정

[[email protected] ~]$ python cisco.py 
Owner of <IPv4 1.1.1.1/32> is 'Interface ge-0/0/0' 
Owner of <IPv4 1.1.1.2/25> is 'Vlan 25 (name: accounting)' 
[[email protected] ~]$ 

답변

4

소유자을 사용하는 현재 접근법이 가장 깨끗한 해결책 일 것입니다.

그렇다면 누가 IP 주소를 소유하고 있는지 알아야 할 경우 gc.get_referrers()이 도움이 될 수 있습니다.

2

. 당신이 근본적으로 묻는 것은 "어떤 물체가이 물체에 대한 언급이 있습니까?"입니다. 물론 일반적인 경우에는 심지어 L3Protocol 인스턴스에 대한 참조를 포함하는 개체가있을 수 있으며 (심지어 각각의 인스턴스에 L3Protocol 인스턴스에 대한 참조가 여러 개 포함될 수 있기 때문에) 의미가 없습니다.

따라서 어떤 방법 으로든 L3Protocol의 소유자를 기록해야하거나 더 많은 정보가있는 상황에서 L3Protocol의 소유자 만 요청해야합니다. owner은 이론적으로 L3Protocol 및 가능한 소유자가있는 유니버스를 사용하고 L3Protocol (또는 None)을 소유 한 유니버스를 반환하는 함수 일 수 있습니다. InterfaceVlan을 모두 기록하는 개체가있는 경우 해당 개체에 대한 메서드를 만드는 것이 좋습니다.

하지만 당신이하고있는 방식이 내가 양방향 링크 (소유자 -> 소유 및 소유 -> 소유권)를 유지할 수있는 한 제멋대로 생각할 수있는 가장 직접적인 방법이라고 생각합니다. 소유자)가 변하면 일관성을 유지해야합니다.