【问题标题】:Printing None instead of nothing when interacting linked list交互链表时打印无而不是无
【发布时间】:2017-09-29 03:44:56
【问题描述】:

我有一个链表,我在一个范围内迭代并返回所有可以表示为该范围内整数的平方数。而不是只返回可以这样做的数字,它将返回None,例如9, None, None...,16, None, None..., 25,我希望它只返回9, 16, 25 etc etc

class Squares:
    def __init__(self, start, end):
        self.__start = start - 1
        self.__end = end -1

    def __iter__(self):
        return SquareIterator(self.__start, self.__end)

class SquareIterator:
    def __init__(self, start, end): 
        self.__current = start
        self.__step = 1
        self.__end = end

    def __next__(self):
        if self.__current > self.__end:
            raise StopIteration 
        else:
            self.__current += self.__step 
        x = self.__current - self.__step + 1
        self.__current - self.__step + 1
        if str(x).isdigit() and math.sqrt(x) % 1 == 0:
            return x

【问题讨论】:

  • 旁注:你认为这里的链表是什么?您在这里所做的没有一件与链表相关。
  • 您是否误会了 linked listiterator 这两个术语?

标签: python python-3.x list loops


【解决方案1】:

你需要让你的__next__函数继续循环,直到达到目标值:

def __next__(self):
    # We're just going to keep looping. Loop breaking logic is below.
    while True:
        # out of bounds
        if self.__current > self.__end:
             raise StopIteration

        # We need to get the current value
        x = self.__current
        # increase the state *after* grabbing it for test
        self.__current += self.__step 

        # Test the value stored above
        if math.sqrt(x) % 1 == 0:
             return x

您应该存储 x,然后递增的原因是无论如何您都必须递增,即使您没有完美的正方形。

【讨论】:

  • 请注意,避免使用专用的迭代器类可能会更容易,只需将__iter__ 用于Squares 作为生成器函数。显式的__next__ 涉及到Python 做的很差的各种低效状态管理,而且并不那么容易理解; __iter__ 作为生成器函数通常非常简单;每次你点击yield 时,它就像来自__next__return,但是你的所有状态都是本地函数,不涉及特殊对象(生成器负责保存和恢复所述本地状态)。
【解决方案2】:

不清楚你为什么要让事情复杂化;有一个简单的方法:

import math

class Squares:
    def __init__(self, start, end):
        self.__start = start
        self.__end = end
        self.__step = 1

    def __iter__(self):
        for x in range(self.__start, self.__end, self.__step):
            if math.sqrt(x) % 1 == 0:
                yield x

s = Squares(0, 100)
for sq in s:
    print(sq, end=' ')

输出:

0 1 4 9 16 25 36 49 64 81 

来自 cmets:

请注意,避免专门的 迭代器类,只需为 Squares 实现 __iter__ 作为生成器 功能。显式__next__涉及各种低效状态 Python 做的不好的管理,而且不是那么容易遵循; __iter__ 作为生成器函数通常非常简单;每次你达到收益时,就像来自__next__ 的回报,但所有 您的状态是本地函数,不涉及特殊对象(生成器 注意保存和恢复所述本地状态)。 – 暗影游侠>

它可能甚至不需要 Squares 类。生成器函数 命名方块会做需要的事情;通过它开始,停止和步进和 将它们用作局部变量,而不是某些属性 不必要的自己。对班级唯一真正的好处是它可以 反复迭代而不重建它,可能不常见的用途 案例

def squares_from(start, stop, step=1):
    """returns a generator function for the perfect squares 
    in the range comprised between start and stop, iterated over using step=step
    """
    for x in range(start, stop, step):
        if math.sqrt(x) % 1 == 0:
            yield x

for sq in squares_from(0, 100):
    print(sq, end=' ')

【讨论】:

  • 哎呀,既然你已经把它写出来了,我可以看到它可能甚至不需要Squares 类。一个名为squares 的生成器函数可以满足需要;传递startstopstep 并将它们用作局部变量,而不是一些不必要的self 的属性。该类唯一真正的优势是它可以重复迭代而不重构它,这可能是一个不常见的用例。
  • 好点;我们不知道的是这段代码的最终目的;也许 OP 为他的班级考虑了其他功能?我会在答案中添加您的评论,因为它很有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多