python - 努力设计这个

时间:2013-03-08 07:26:08

标签: python

我今天在课堂上进行了一次测验,但我失败了,测验如下。 有人可以帮我解释一下。

  1. 向Link添加一个方法open(),将它从链接'左侧'断开,从而打开项链,同时保持链条不间断向右。例如,如果在link1抓住项链,则调用link1.open()会将link3link1断开连接,但仍会保留一个link1link3的链已连接。
  2. 这就是我目前所拥有的:

    class Diamond(object):
        def __str__(self):
            return "Diamond"
    
    class Ruby(object):
        def __str__(self):
            return "Ruby"
    
    class Visitor:
        def __str__(self):
            return self.__class__.__name__
    
    class Link(object):
        def __init__(self, index, jewel = None):
            self.jewel = jewel
            self.index = index
    
        def connectTo(self, link):
            self.nextLink = link
    
        def __next__(self):
            return self.nextLink or None
    
        def attach(self, jewel):
            if not self.jewel:
                self.jewel = jewel
    
        def detatch(self):
            stone = self.jewel
            self.jewel = None
            return stone
    
        def open(self):
            pass
    
        def __str__(self):
            return "link%d" % (self.index)
    
    class Necklace(object):
        def __init__(self, base):
            self.base = base
    
        def describe(self):
            link = self.base
            while True:
                print link, "with", link.jewel, "attatched to", link.nextLink, "with", link.nextLink.jewel
                link = link.nextLink
                if link == self.base:
                    break
    
        def getJewel(self):
            link = self.base
            while True:
                link = link
                if isinstance(link.jewel, Diamond):
                    print "a", link.detatch()
                    break
                link = link.nextLink
                if link == self.base:
                    print "nothing..."
                    break
    
        def acceptVisitor(self, visitor):
            visitor.visit(self)
    
    class DiamondThief(object, Visitor):
        def __init__(self, base):
            self.base = base
            self.jewel = self.base.jewel
    
        def visit(self, necklace):
            necklace.getJewel()
    
        def searchForDiamond(self):
            self.visit(myNecklace)
    
    link1 = Link(1, Ruby())
    link2 = Link(2, Diamond())
    link3 = Link(3, Ruby())
    link1.connectTo(link2)
    link2.connectTo(link3)
    link3.connectTo(link1)
    myNecklace = Necklace(link1)
    myNecklace.describe()
    
    print "Uh on here comes a thief..."
    thief = DiamondThief(link1)
    print "Oh no he took "
    thief.searchForDiamond()
    myNecklace.describe()
    

2 个答案:

答案 0 :(得分:1)

让我们看看每个课程需要哪些功能

  1. Link
    • 变量
      • name(只是可能)
      • linked_tonextlink
      • jewel
    • 方法
      • connectTo(self,link)
      • attach(self,jewel)
      • detach(self)
      • open(self)
      • get_next(self)
  2. Necklace(不在下面的代码中,自行制作)
    • 变量
      • connections
    • 方法
      • __next__(self)next_link(self)
  3. DiamondThief
    • 变量
      • link
      • diamond
    • 方法
      • getDiamond(self)
      • search(self)
  4. Jewels,例如DiamondRuby
    • 没有变量或方法
  5. 看到这段代码,我还添加了DiamondThief类......

    class Necklace:
        '''My version of necklace'''
        def __init__(self, link):
            self.first = link
            self.current_link = link
        def next(self):
            self.current_link = self.current_link.get_next()
            if self.current_link == self.first:
                raise StopIteration
            return self.current_link
        def __iter__(self):
            return self
    
    class Link(object):
        """A link of a necklace"""
        def __init__(self, name, jewel=None):
            self.name = name
            self.linkedTo = None
            self.jewel = None
            if jewel != None:
                self.attach(jewel)
    
        def connectTo(self, link):
            '''Connect to link'''
            if isinstance(link,Link):
                self.linkedTo = link
            else:
                raise TypeError
    
        def attach(self, jewel):
            '''Attach jewel'''
            if self.jewel == None:
                self.jewel = jewel
            else:
                msg = 'There is already a %s attached' % jewel.__class__.__name__
                raise AttributeError(msg)
    
        def detach(self):
            '''Detach jewel'''
            if self.jewel != None: # 
                je = self.jewel
                self.jewel = None
                return j
            else:
                msg = 'There is nothing to detach'
                raise AttributeError(msg)
    
        def __str__(self):
            if self.linkedTo != None:
                return "%s(%s) => %s" % \
                       (self.name,self.jewel.__class__.__name__, self.linkedTo.name)
            else:
                return "%s(%s) => %s" % \
                       (self.name,self.jewel.__class__.__name__,None)
    
        def get_next(self):
            '''Get the next chain'''
            return self.linkedTo
    
    class Diamond(object):
        pass
    
    class Ruby(object):
        pass
    
    class DiamondThief:
        def __init__(self, necklace):
            self.necklace = necklace
            self.diamond = None
    
        def search(self):
            '''Go link by link to find the Diamond'''
            if self.diamond != None:
                print 'Have a diamond already'
                return 
            first = self.necklace.first
            link = first
            for link in self.necklace: # loop till
                if isinstance(link.jewel, Diamond): # diamond is found
                    self.diamond = link.jewel
                    link.jewel = None
                    print 'Found Diamond'
                    break
    
        def getDiamond(self):
            if self.diamond != None:
                return self.diamond
            else:
                return None
    
    def main():
        # create
        l1 = Link('1',Diamond())
        l2 = Link('2',Ruby())
        l3 = Link('3', Ruby())
        l1.connectTo(l2)
        l2.connectTo(l3)
        l3.connectTo(l1)
        i = DiamondThief()
        try:
            l2.attach(Ruby())
        except AttributeError,e:
            print e
        print l1
        print l2
        print l3
        print '-'*16
        i.search()
        print l1
        print l2
        print l3
    main()
    

答案 1 :(得分:0)

第1部分简单地要求您使用Link类中描述的方法来构建指定项链:

link1 = Link()
link1.attach(Ruby())
link2 = Link()
link2.attach(Diamond())
link3 = Link()
link3.attach(Ruby())

link1.connectTo(link2)
link2.connectTo(link3)
link3.connectTo(link1)

myNecklace = link1

第2部分需要实现Link和DiamondThief类。

以下是我实现Link的方式,作为双向链表。您实际上并不需要第二个链接来实现我们在此部分中需要执行的基本方法,但如果我们同时引用左侧和右侧邻居链接,则在第3部分中添加open会更容易。

class Link(object):
    def __init__(self):
        """Initialize an empty link."""
        self.left = None
        self.right = None
        self.jewel = None

    def connectTo(self, other):
        """Connect another link to the right of this one."""
        if self.right or other.left:
            raise ValueError("Links already have connections")
        self.right = other
        other.left = self

    def attach(self, jewel):
        """Add a jewel to this link."""
        if self.jewel:
            raise ValueError("Link already has a jewel attached")
        self.jewel = jewel

    def detatch(self):
        """Remove and return the jewel attached to this link."
        jewel = self.jewel
        self.jewel = None
        return jewel

以下是DiamondThief访客的实施情况。它的主要方法是visit递归访问后续的Link实例,直到找到钻石或循环(或从一条打开的项链的末端开始运行)。您可以使用while循环而不是递归来执行相同的操作,但这似乎更简单。请注意,递归调用中的or表达式表示如果first为None(默认情况下为默认值),则link将作为first传递。

class DiamondThief(object):
    def __init__(self):
        """Initialize a DiamondThief"""
        self.diamond = None

    def visit(self, link, first=None):
        """Recursively visit a necklace, searching for a Diamond to steal."""
        if link == first: # looped
            return
        if isinstance(link.jewel, Diamond): # diamond found
            self.diamond = link.detatch()
            return
        if link.right is not None: # not at an open end
            self.visit(link.right, first or link)

    def getDiamond(self):
        return self.diamond

第3部分要求您向open类添加Link方法。由于Link是双重关联的,因此很容易将列表拆分到当前位置的左侧。如果你将它实现为单链表,你必须扫描整条项链(从每个链接到它的右邻居),直到找到链接回第一个实例的项链。对于没有形成环的项链,它根本不起作用。

无论如何,这是简单的实现:

def open(self):
    """Disconnect this link from it's left neighbor."""
    if self.left is None:
        raise ValueError("Link is not connected on the left")
    self.left.right = None
    self.left = None