Python作业之类的练习(20190520)

Python作业之类的练习(20190520)

1.用面向对象实现LinkedList链表

单向链表实现append、iternodes方法

  • 单向链表第一版(比较烂)
# 单向链表
class Linked:
    _length = 0
    def __init__(self,iterable=None):
        self._value = None
        self._next = None
        self._endvalue = self

        if iterable is None: return
        for i in iterable:
            self.append(i)

    @property
    def length(self):
        return self._length

    def append(self,value):
        link = Linked()
        link._value = value
        self._endvalue._next = link
        self._endvalue = link
        self._length += 1

    def iternodes(self):
        val = self._next
        while val:
            yield val._value
            val = val._next

    def __str__(self):
        return "<linked ["+ " ".join(map(str,self.iternodes())) + "]>"


a = Linked(_ for _ in range(5))
a.append(None)
a.append("5")
a.append("60")

print("长度:",a.length)
print(a)
# for i in a.iternodes():
#     print(i)

link_001

  • 单向链表第二版
# 单向链表第二版
class Linked:
    class __Link:
        __slots__ = "value","next"
        def __init__(self,value):
            self.value = value
            self.next = None

    def __init__(self,iterable=None):
        self.__start = None #起始值
        self.__end = None #结束值
        self.__lenght = 0
        if iterable is None:return
        for i in iterable:
            self.append(i)

    def __len__(self):
        return self.__lenght

    def append(self,value):
        link = Linked.__Link(value)
        if not self:
            self.__start = link
            self.__end = link
        else:
            self.__end.next = link
            self.__end = link
        self.__lenght += 1

    def iternodes(self):
        val:Linked.__Link = self.__start
        while val:
            yield val.value
            val = val.next

    def remove(self,value):
        if not self: raise ValueError("{} 值不存在".format(value))
        if self.__start.value == value:
            self.__start = self.__start.next
        else:
            val = self.__start
            while val:
                if val.next and val.next.value==value:
                    val.next = val.next.next
                    if not val.next: self.__end = val  #刪除的值是最后一个值
                    return
                val = val.next
            else:
                raise ValueError("{} 值不存在".format(value))

    def pop(self):
        if self:
            val = self.__getitem(self.__lenght-2)
            val.next = None
            value = self.__end.value
            self.__end = val
            self.__lenght -= 1
            return value
        else:
            raise IndexError("pop form empty DoubleLink")

    def insert(self,num:int,value):
        if not isinstance(num, int): raise TypeError("num 必须是int类型,而{}是{}类型".format(num, type(num)))
        # 负索引转正索引
        num = num if num>=0 else (0 if num+self.__lenght<=0 else num+self.__lenght)

        if self.__lenght<=num: #尾部追加
            self.append(value)
        elif num == 0 :
            val = Linked.__Link(value)
            val.next = self.__start
            self.__start = val
            self.__lenght += 1
        else:
            val = self.__getitem(num-1)
            link = Linked.__Link(value)
            link.next = val.next
            val.next = link
            self.__lenght += 1


    def __getitem(self,index:int):
        if not isinstance(index,int):raise TypeError("index 必须是int类型,而{}是{}类型".format(index,type(index)))
        if 0<=index<len(self):
            val:Linked.__Link = self.__start
            i = 0
            while val:
                if i==index:
                    return val
                else:
                    val = val.next
                    i += 1
        else:
            raise KeyError("{} 索引错误".format(index))

    def __repr__(self):
        return "(Linked <" + ",".join(map(str,self.iternodes())) + ">)"

    def __iter__(self):
        return iter(self.iternodes())

    def __add__(self, value):
        self.append(value)
        return self

    def __sub__(self, other):
        self.remove(other)
        return self

    def __getitem__(self, num:int):
        return self.__getitem(num).value

    def __setitem__(self, key, value):
        self.__getitem(key).value = value



link = Linked()
link = link + 0+1+2+3+4+5
link = link-0-2-5
print(link)
link.append(10)
link = link +5 +6
print(link)
link += 6
link -= 4
print(link)

link_002

双向链表实现append、pop、insert、remove、iternodes方法

  • 双向链表第一版(比较烂)
# 双向链表
class DoubleLink:
    """双向链表"""
    _length = 0

    class __Link:
        __slots__ = "value","before","after"

        """帮助记录双向链表元素"""
        def __init__(self, value, before=None, after=None):
            self.value = value  # 当前值
            self.before = before  # 前一个值
            self.after = after  # 后一个值

    def __init__(self,iterable=None):
        self._start = None
        self._end = None
        if iterable:
            for i in iterable:
                self.append(i)

    @property
    def length(self):
        return self._length

    def append(self,value):
        link = DoubleLink.__Link(value)
        self._length +=1
        if self._end is None: #如果初始值一个都没有,设置初始值
            self._end = link
            self._start = link
        else: #添加链表
            self._end.after = link
            link.before = self._end
            self._end = link

    def pop(self):
        #集合为空,则抛出异常
        if self._end is None:
            raise IndexError("pop form empty DoubleLink")
        value = self._end.value
        self._end = self._end.before #前一个值赋给最后一个值
        if self._end is None: #如果为空,证明已经没有数据了,将开始设置为空
            self._start = None
            self._length = 0
        else:
            self._end.after = None #修改最后一个值的下一个值
            self._length -= 1
        return value

    def insert(self,index,value):
        #检测索引类型
        if not isinstance(index,int):
            raise TypeError("'{}' object cannot be interpreted as an integer".format(type(index).__name__))

        #规范索引
        if index >=0 : #正向索引
            index = index if index<self._length else self._length #解决正向超界
        else: #负向索引
            val = index + self._length
            index = 0 if val<=0 else val #解决负向超界

        #插入值
        if self._end is None and self._start is None: #原集合中没有值
            self.append(value)
        else:
            temp = None
            if self._length/2 >index: #从开始位置寻找
                temp = self._start
                for i in range(index):
                    temp = temp.after
            else: #从结束位置寻找
                for i in range(self._length - index):
                    if not temp:
                        temp = self._end
                    else:
                        temp = temp.before
            #开始插入
            if not temp: #尾部插入
                # link = DoubleLink.__Link(value,self._end)
                # self._end.after = link
                # self._end = link
                self.append(value)
            elif temp is self._start: #开始位置插入
                link = DoubleLink.__Link(value,None, self._start)
                temp.before = link
                self._start = link
                self._length += 1
            else: #中间插入
                link = DoubleLink.__Link(value,temp.before,temp)
                temp.before.after = link
                temp.before = link
                self._length += 1

    def remove(self,value): #移除指定值
        link  = self._start

        # 寻找值对应的link
        temp = None
        while link:
            if value == link.value:
                temp = link
                break
            else:
                link = link.after
        else: #值不存在,抛出异常
            raise ValueError("DoubleLink.remove(x): x not in list")

        #修改temp.befor.after 前一个值中指向的下一个值
        if temp.before: #移除值
            temp.before.after = temp.after
        else: #说明是开始值
            self._start = temp.after
        #修改after.before 后一个值中指向的前一个值
        if temp.after:
            temp.after.before = temp.before
        else: #说明是结束值
            self._end = temp.before
        self._length -= 1

    def iternodes(self):
        """遍历链表"""
        link = self._start
        while link:
            yield link.value
            link = link.after

    def __repr__(self):
        return "<DoubleLink [" + ",".join(map(str,self.iternodes())) + "] >"

if __name__ == "__main__":
    dlink = DoubleLink([1,2,3,4,None,5,6])
    print(dlink)
    print(dlink.pop())
    print(dlink,"\t长度;",dlink.length)
    dlink.remove(None)
    dlink.remove(1)
    print(dlink, "\t长度;", dlink.length)
    dlink.append(9)
    print(dlink, "\t长度;", dlink.length)
    dlink.remove(9)
    dlink.append(10)
    print(dlink, "\t长度;", dlink.length)
    dlink.insert(10,5)
    dlink.append(9)
    dlink.insert(-100, -10)
    print(dlink, "\t长度;", dlink.length)
    dlink = DoubleLink()
    dlink.insert(-100, -20)
    dlink.insert(-100, -30)
    dlink.insert(0, 0)
    dlink.insert(2, 2)
    dlink.insert(4, 4)
    dlink.insert(100, 5)
    print(dlink, "\t长度;", dlink.length)
    for i in range(dlink.length-3):
        dlink.pop()

    print(dlink, "\t长度;", dlink.length)

link_003

  • 双向链表第二版
# 双向链表第二版
class DoubleLink:
    """双向链表"""

    class __Link:
        """帮助记录双向链表元素"""
        def __init__(self, value, before=None, after=None):
            self.value = value  # 当前值
            self.before = before  # 前一个值
            self.after = after  # 后一个值

    def __init__(self,iterable=None):
        self._start = None
        self._end = None
        self._length = 0
        if iterable:
            for i in iterable:
                self.append(i)

    @property
    def length(self):
        return self._length

    def append(self,value):
        link = DoubleLink.__Link(value)
        self._length +=1
        if self._end is None: #如果初始值一个都没有,设置初始值
            self._end = link
            self._start = link
        else: #添加链表
            self._end.after = link
            link.before = self._end
            self._end = link

    def pop(self):
        #集合为空,则抛出异常
        if self._end is None:
            raise IndexError("pop form empty DoubleLink")
        value = self._end.value
        self._end = self._end.before #前一个值赋给最后一个值
        if self._end is None: #如果为空,证明已经没有数据了,将开始设置为空
            self._start = None
            self._length = 0
        else:
            self._end.after = None #修改最后一个值的下一个值
            self._length -= 1
        return value

    def insert(self,index,value):
        #检测索引类型
        if not isinstance(index,int):
            raise TypeError("'{}' object cannot be interpreted as an integer".format(type(index).__name__))

        #规范索引
        if index >=0 : #正向索引
            index = index if index<self._length else self._length #解决正向超界
        else: #负向索引
            val = index + self._length
            index = 0 if val<=0 else val #解决负向超界

        #插入值
        if self._end is None and self._start is None: #原集合中没有值
            self.append(value)
        else:
            temp = None
            if self._length/2 >index: #从开始位置寻找
                temp = self._start
                for i in range(index):
                    temp = temp.after
            else: #从结束位置寻找
                for i in range(self._length - index):
                    if not temp:
                        temp = self._end
                    else:
                        temp = temp.before
            #开始插入
            if not temp: #尾部插入
                # link = DoubleLink.__Link(value,self._end)
                # self._end.after = link
                # self._end = link
                self.append(value)
            elif temp is self._start: #开始位置插入
                link = DoubleLink.__Link(value,None, self._start)
                temp.before = link
                self._start = link
                self._length += 1
            else: #中间插入
                link = DoubleLink.__Link(value,temp.before,temp)
                temp.before.after = link
                temp.before = link
                self._length += 1

    def remove(self,value): #移除指定值
        link  = self._start
        # 寻找值对应的link
        temp = None
        while link:
            if value == link.value:
                temp = link
                break
            else:
                link = link.after
        else: #值不存在,抛出异常
            raise ValueError("DoubleLink.remove(x): x not in list")

        #修改temp.befor.after 前一个值中指向的下一个值
        if temp.before: #移除值
            temp.before.after = temp.after
        else: #说明是开始值
            self._start = temp.after
        #修改after.before 后一个值中指向的前一个值
        if temp.after:
            temp.after.before = temp.before
        else: #说明是结束值
            self._end = temp.before
        self._length -= 1

    def iternodes(self):
        """遍历链表"""
        link = self._start
        while link:
            yield link.value
            link = link.after

    def __repr__(self):
        return "<DoubleLink [" + ",".join(map(str,self.iternodes())) + "] >"

    def __len__(self):
        return self._length

    def __iter__(self):
        return iter(self.iternodes())

    def __getitem__(self, index:int):
        return self.__getitem(index).value

    def __setitem__(self, index:int, value):
        self.__getitem(index).value = value

    def __add__(self, other):
        self.append(other)
        return self

    def __radd__(self, other):
        self.insert(0,other)
        return self

    def __sub__(self, other):
        self.remove(other)
        return self

    def __getitem(self, index:int):
        if 0<=index<self.length:
            if index<=self.length//2: #正向寻找
                link:DoubleLink.__Link = self._start
                for i in range(index):
                    link = link.after
                return link
            else: #反向寻找
                link:DoubleLink.__Link = self._end
                for i in range(self.length - index-1):
                    link = link.before
                return link
        else:
            raise KeyError("{} DoubleLink index out of range".format(index))




if __name__ == "__main__":
    dlink = DoubleLink([1,2,3,4,None,5,6])
    print(dlink)
    print(dlink.pop())
    print(dlink,"\t长度;",dlink.length)
    dlink.remove(None)
    dlink.remove(1)
    print(dlink, "\t长度;", dlink.length)
    dlink.append(9)
    print(dlink, "\t长度;", dlink.length)
    dlink.remove(9)
    dlink.append(10)
    print(dlink, "\t长度;", dlink.length)
    dlink.insert(10,5)
    dlink.append(9)
    dlink.insert(-100, -10)
    print(dlink, "\t长度;", dlink.length)
    dlink = DoubleLink()
    dlink.insert(-100, -20)
    dlink.insert(-100, -30)
    dlink.insert(0, 0)
    dlink.insert(2, 2)
    dlink.insert(4, 4)
    dlink.insert(100, 5)
    print(dlink, "\t长度;", dlink.length)
    for i in range(dlink.length-3):
        dlink.pop()

    print(dlink, "\t长度;", dlink.length)
    print(dlink[1])
    dlink += 5
    dlink +5+6+9
    5+dlink+6+9
    print(dlink)
    dlink -5-0-9-6-9-5-6-5-2-(-30)
    5+dlink+6+7+9
    print(dlink)
    dlink[0] = -10
    print(dlink)

link_004

  • 双向链表第三版

class Node:
    __slots__ = 'item next prev'.split()

    def __init__(self, item, next=None, prev=None):
        self.item = item
        self.next = next # Node  instance
        self.prev = prev # Node  instance

    def __repr__(self):
        return "{} <== {} ==> {}".format(
            self.prev.item if self.prev else None,
            self.item,
            self.next.item if self.next else None
        )

class LinkedList: # Double
    def __init__(self):
        self.head = None
        self.tail = None # ?
        self._size = 0

    def append(self, value):
        node = Node(value) # 下一个是None的节点

        if self.tail is None: # empty
            self.head = node
        else:
            self.tail.next = node
            node.prev = self.tail
        self.tail = node
        self._size += 1
        return self

    def __add__(self, item):
        return self.append(item)

    def insert(self, index, value):
        if index >= len(self):
            self.append(value)
            return

        if index < -len(self):
            index = 0

        current = self[index]

        # 找到了,容器非空
        newnode = Node(value)
        prev = current.prev
        next = current
        # 开头插入
        if prev is None: # i==0 index==0 self.head == current
            self.head = newnode
        else: # 非开头
            newnode.prev = prev
            prev.next = newnode
        newnode.next = next
        next.prev = newnode

        self._size += 1


    def pop(self):
        if self.tail is None:
            raise Exception("empty")

        node = self.tail
        prev = node.prev
        # only one
        if prev is None:#self.head.next is None:
            self.head = None
            self.tail = None
        else:
            prev.next = None
            self.tail = prev

        value = node.item
        self._size -= 1
        return value


    def remove(self, index):
        if self.tail is None:
            raise Exception("empty")

        current = self[index]

        prev = current.prev
        next = current.next

        if prev is None and next is None:#self.head == self.tail just one
            self.head = None
            self.tail = None
        elif prev is None: # 头
            self.head = next
            next.prev = None
        elif next is None: # 尾
            self.tail = prev
            prev.next = None
        else: # 中间
            prev.next = next
            next.prev = prev

        del current
        self._size -= 1


    def iternodes(self, reverse=False):
        current = self.tail if reverse else self.head
        while current:
            yield current
            current = current.prev if reverse else current.next

    # 容器
    def __len__(self):
        return self._size

    size = property(lambda self: self._size)

    def __getitem__(self, index):
        if index >= len(self) or index < -len(self):
            raise IndexError('out of index : {}'.format(index))

        reverse = True if index < 0 else False
        start = 1 if index < 0 else 0

        for i, node in enumerate(self.iternodes(reverse), start):
            if i == abs(index):
                return node

    def __setitem__(self, index, value): # 改
        self[index].item = value

    def __reversed__(self): # 此魔术方法可以不实现,但是要使用reversed内建函数,必须有__len__和__getitem__
        # for x in self.iternodes(True):
        #     yield x
        #yield from self.iternodes(True)
        return self.iternodes(True)

    # def __iter__(self):
    #     return self.iternodes()

    __iter__ = iternodes

    def __contains__(self, item):
        print(item, '~~~~~~~~~~~~~~~~~')
        current = self.head
        while current:
            if item == current.item:
                return True
            current = current.next
        return False



ll = LinkedList()
ll + 1 + 2 + 3 + 4 + 5
ll.insert(0, 'start')
ll.insert(1000, 'end')

for x in ll:
    print(x)

print('-' * 30)
print(ll[1], len(ll))
print()
for x in reversed(ll):
    print(x)

print(2 in ll)
ll[0] = 'start~~~~'
print('-' * 30)
for x in ll:
    print(x)

[外链图片转存失败(img-4iaZh1I6-1563623371007)(https://raw.githubusercontent.com/1263351411/xdd.github.io/master/img/python/link_005.jpg)]

2.手动实现staticmethod装饰器功能

class StaticMethod:
    """静态方法装饰器,类似于staticMethod"""
    def __init__(self,fn):
        self.fn = fn

    def __get__(self, instance, owner):
        return self.fn

3.手动实现classmethod装饰器功能

class ClassMethod:
    """类方法装饰器,类似于classmethod"""
    def __init__(self,fn):
        self.fn = fn

    def __get__(self, instance, owner):
        def _fn(*args,**kwargs):
            return self.fn(owner,*args,**kwargs)
        functools.update_wrapper(_fn,self.fn)
        # return functools.partial(self.fn,owner) #也可以使用偏函数
        return _fn

4.手动实现property装饰器功能

  • 第一版(比较烂)
class Property:
    def __init__(self,fn):
        self._fn = fn

    def setter(self,fn):
        self.set = fn
        return self

    def deleter(self,fn):
        self.defn = fn
        return self

    def __delete__(self, instance):
        self.defn(instance)

    def __get__(self, instance, owner):
        return self._fn(instance)

    def __set__(self, instance, value):
        # print("---set")
        self.set(instance,value)

class A:
    def __init__(self,data):
        self._data = data

    @Property
    def data(self):
        return self._data

    @data.setter
    def data(self,value):
        self._data = value

    @data.deleter
    def data(self):
        print("data被銷毀了")

a = A("tom")
print(a.data)
a.data = 5
print(a.data)
del a.data
print("-----------演示完成")

link_006

  • 第二版
class Property:
    """自己实现property和Property功能一样"""
    def __init__(self,fn):
        self._fn = fn

    def setter(self,fn):
        self.set = fn
        return self

    def deleter(self,fn):
        self.defn = fn
        return self

    def __delete__(self, instance):
        if hasattr(self,"defn"):
            self.defn(instance)

    def __get__(self, instance, owner):
        return self._fn(instance)

    def __set__(self, instance, value):
        if not hasattr(self,"set"):
            raise AttributeError("can't set attribute")
        self.set(instance,value)
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值