繁体   English   中英

Python3:如何控制用户定义类的行为?

[英]Python3: How can I control behavior of user defined class?

有这样的排序功能:

def iterative_insertion_sort(A):
    '''Sort A iteratively.'''
    for i, key in enumerate(A[1:]):
        while i > -1 and A[i] > key:
            print(id(key), id(A[i+1]))
            A[i + 1] = A[i]
            print(id(key), id(A[i+1]))
            i = i - 1
        A[i + 1] = key

排序功能在浮点数方面效果很好。

样本输出:./insertion_sort.py .23 .21 .26

140566861513304 140566861513304
140566861513304 140566861513256
[0.21, 0.23, 0.26]

但是我有一个名为lList的自定义类,它具有链接(另一个自定义类)类型的元素。 当我输入lList的实例时,排序无法正常进行。

样本输出:0.23 0.21 0.26 /

139732300992808 139732300992808
139732300992808 139732300992808
0.23 0.23 0.26 /

如我们所见,在使用float的情况下,赋值语句之后key和array元素的id不同。 但是对于自定义类,即使在分配操作之后,键和数组元素的ID也相同。 这是麻烦的原因。

我怀疑问题是因为浮点数是不可变的,而我的自定义类不是。 我的问题是解决情况的最佳方法是什么?

注意:在排序过程中,我希望零到最小变化。 但是,我愿意自定义我的lList或链接类。

PS我刚刚只发布了相关的代码段。 如果还需要类定义,只需提及它,我也会添加它。

非常感谢!

更新:

链接定义:

class link:
    '''Implement link.'''

    def __init__(self, key=None):
        self.key = key
        self.nxt = None
        self.prev = None

    def __str__(self):
        '''Print link.'''
        if self:
            return str(self.key)
        else:
            return '/'

    def __gt__(self, other):
        return self.key > other.key

这是lList定义:

class lList:
    '''Implement list of links.'''

    def __init__(self):
        self._head = None
        self._numberOfLinks = 0

    def list_insert(self, x):
        '''Insert link x at the beginning of list.'''
        x.nxt = self._head
        if self._head:
            self._head.prev = x
        self._head = x
        self._numberOfLinks += 1

    def __str__(self):
        '''Print list of links.'''
        listFormat = ''
        temp = self._head
        while temp:
            listFormat += str(temp) + ' '
            temp = temp.nxt
        else:
            listFormat += '/ '
        return listFormat

    def get_data(self, position):
        '''Return link from list at position position from head.'''
        i = 0
        temp = self._head
        while i < position:
            temp = temp.nxt
            i += 1
        return temp

    def set_data(self, position, newLink):
        '''Overwrite key of link at position distance from head of list with key of newLink.'''
        i = 0
        temp = self._head
        while i < position:
            temp = temp.nxt
            i += 1
        temp.key = newLink.key    

    def __getitem__(self, position):
        if type(position) is slice:
            return [self[i] for i in range(*position.indices(len(self)))]
        elif type(position) is int:
            if position < 0:
                position += len(self)
            if position >= len(self):
                raise IndexError("The index (%d) is out of range."%position)
            return self.get_data(position)
        else:
            raise TypeError("Invalid argument type.")

    def __setitem__(self, position, value):
        self.set_data(position, value)

    def __len__(self):
        return self._numberOfLinks

这是创建相同场景的最少代码:

test = lList()
l = link(.26)
test.list_insert(l)
l = link(.21)
test.list_insert(l)
l = link(.23)
test.list_insert(l)
print(test)
iterative_insertion_sort(test)
print(test)

是的,问题不只是不变性之一,而更多是共享参考。

在对浮点值进行排序时,将对存储在A[1]中的浮点数的引用存储在key 然后,使用A[0]的值更改A[1]的引用。 这意味着A[1]现在指向另一个对象,稍后将A[0]设置为key就可以了。

但是,在对链表进行排序时,您永远不会更改A[1] 您更改A[1] 的属性 keyA[1]继续指向同一link实例,并且在key.key也可以看到设置A[1].key

您可以通过将整个link对象实际替换为新的link对象来解决此问题:

def set_data(self, position, newLink):
    '''Overwrite key of link at position distance from head of list with key of newLink.'''
    i = 0
    temp = self._head
    while i < position:
        temp = temp.nxt
        i += 1
    newlink = link(newLink.key)
    if temp.prev:
        temp.prev.nxt = newlink
    else:
        self._head = newlink
    newlink.nxt = temp.nxt

这等同于在Python list对象中设置新值:

(4302695168, 4302695168)
(4302695168, 4303149248)
0.21 0.23 0.26 / 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM