0

我今天在课堂上有一个测验,我很惨地失败了,测验如下。有人可以帮我解释一下吗。

  1. 向 Link添加一个方法open(),将其从“左侧”的 Link 断开,从而打开项链,同时保持右侧的链条完好无损。例如,如果在 处抓住项链link1,则呼叫link1.open()将断开连接link3link1但仍使持有链的人保持link1连接状态link3

这是我目前拥有的:

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()
4

2 回答 2

1

让我们看看我们在每个类中需要哪些功能

  1. Link
    • 变量
      • name(只是也许)
      • linked_to或者nextlink
      • 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
    • 没有变量或方法

看到这段代码,我还添加了 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()
于 2013-03-08T08:17:54.243 回答
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, 作为一个双向链表。您实际上并不需要第二个链接来实现我们在这部分中需要做的基本方法,但是open如果我们同时引用左右相邻链接,在第 3 部分中添加会容易得多。

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递归调用中的表达式意味着 iffirst为 None (默认情况下将是) thenlink将作为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
于 2013-03-08T10:48:21.970 回答