迭代函数,保存在自身属性中

本文介绍了一个使用JavaScript实现的阶乘函数,并通过缓存机制来提高递归调用的效率。文中探讨了如何避免非正整数输入导致的NaN返回值问题。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>
    <script>
        
        function factorial(n){
     //判断n是否为正整数,n==Math.round(n)不错
    if (isFinite(n) && n>0 && n==Math.round(n)) { //之前看错了,这是round看成了random
        if (!(n in factorial)) {
            //创建数组,保存阶乘结果
            factorial[n] = n*factorial(n-1);
            // return factorial[n];  这一句写错位置了
        }
        return factorial[n]; 
    }
    //如果输入项不是正整数了,返回NaN.
    else {
        return NaN;
    }
}
//这一句一定要有,否则就返回了NaN
factorial[1] = 1;  //初始化缓存,以保证这种初始情况。
factorial(10);

    </script>
</body>
</html>

我在想:

  如果没有初始化,该怎么写不返回NaN;

等我能力提高点,再来看这个问题

转载于:https://www.cnblogs.com/nostic/articles/5902338.html

<think>我们使用生成器函数(使用yield)来实现链表的迭代功能。在链表的节点类中,我们可以定义一个__iter__()方法,该方法是一个生成器函数,它从当前节点开始遍历整个链表,每次yield当前节点的值(或节点本身),然后移动到下一个节点,直到链表末尾。 根据引用[1],迭代器需要实现__iter__()和__next__()方法,但如果我们使用生成器,则无需显式定义__next__(),因为生成器会自动实现迭代器协议。 具体步骤: 1. 在链表节点类(ListNode)中定义__iter__()方法。 2. 在__iter__()方法中,使用一个循环(从当前节点开始,直到None结束)遍历链表。 3. 在循环中,使用yield返回当前节点的值(或节点本身)。 4. 然后将当前节点移动到下一个节点。 注意:这里我们假设链表节点类已经定义,每个节点有属性val和next。 实现代码: 如果我们希望迭代时返回节点的值: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def __iter__(self): current = self while current: yield current.val current = current.next ``` 如果我们希望迭代时返回节点本身(这样我们可以访问节点的所有属性): ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def __iter__(self): current = self while current: yield current current = current.next ``` 使用示例(迭代节点值): ```python # 创建链表: 1->2->3 head = ListNode(1) head.next = ListNode(2) head.next.next = ListNode(3) # 遍历链表的值 for value in head: print(value) # 输出1, 2, 3 # 或者使用next()函数手动迭代 it = iter(head) # 调用head.__iter__(),返回生成器对象(也是迭代器) print(next(it)) # 1 print(next(it)) # 2 print(next(it)) # 3 print(next(it)) # 抛出StopIteration异常 ``` 使用示例(迭代节点本身): ```python for node in head: print(node.val) # 同样输出1,2,3 ``` 注意:这里我们是在每个节点上实现了__iter__(),所以我们可以直接从任意节点开始迭代其后所有节点。但通常,我们可能有一个链表类(LinkedList)来管理整个链表,那么可以在链表类中实现__iter__(),这样更符合封装原则。 如果我们有一个链表类(如引用[2]和[3]中提到的),那么可以在链表类中实现__iter__(),例如: ```python class LinkedList: def __init__(self): self.head = None # 头节点 self.tail = None # 尾节点 def append(self, val): # 添加节点的方法(省略具体实现) pass def __iter__(self): current = self.head while current: yield current.val # 或者 yield current current = current.next ``` 但注意,在链表类中实现__iter__(),我们是从头节点开始遍历的。 总结: 使用yield实现链表迭代的步骤: 1. 从起始节点(head)开始。 2. 循环直到当前节点为None。 3. 每次循环中,yield当前节点的值(或节点本身)。 4. 将当前节点更新为下一个节点。 这样,我们就可以使用for循环或next()函数来遍历链表了。 注意:在Python中,生成器函数(包含yield的函数)在调用时返回一个生成器对象,该对象自动实现了迭代器协议(即具有__iter__()和__next__()方法)。因此,我们无需自己编写__next__()方法,生成器会自动处理StopIteration异常。 相关问题: 1. 如何在迭代链表的同时修改节点的值? 2. 如何实现双向链表的双向迭代(正向和反向)? 3. 生成器实现迭代器与经典迭代器模式有何优缺点? 4. 如果链表在迭代过程中被修改(如节点被删除),会发生什么情况?如何避免? 5. 如何实现链表的切片操作(如获取子链表)?</think>在 Python 中使用 `yield` 和 `next` 实现链表迭代功能是一种高效且简洁的方式,它利用生成器自动处理迭代器协议。以下是详细实现方法和原理说明: ### 实现步骤 1. **定义节点类**:创建链表基本结构 2. **实现 `__iter__()` 方法**:使用生成器函数遍历链表 3. **使用 `yield` 返回节点值**:每次迭代产生一个值 4. **移动指针**:通过 `current = current.next` 遍历链表 ```python class ListNode: def __init__(self, val=0, next=None): self.val = val # 节点存储的值 self.next = next # 指向下一个节点的指针 def __iter__(self): """生成器实现的迭代方法""" current = self # 从当前节点(head)开始 while current: # 当节点存在时继续迭代 yield current.val # 产生当前节点的值 current = current.next # 移动到下一个节点 ``` ### 关键组件解析 1. **`yield` 关键字**: - 将方法转换为生成器函数 - 每次调用 `next()` 时执行到下一个 `yield` 语句 - 自动保存当前执行状态[^1] 2. **`next()` 函数**: - 触发生成器执行到下一个 `yield` - 当没有更多节点时自动引发 `StopIteration` 3. **节点指针移动**: - `current = self`:从 head 节点开始 - `current = current.next`:移动到下一个节点 - 当 `current` 为 `None` 时结束迭代 ### 使用示例 ```python # 创建链表: 1 → 2 → 3 → 4 head = ListNode(1) head.next = ListNode(2) head.next.next = ListNode(3) head.next.next.next = ListNode(4) # 使用 for 循环迭代 print("自动迭代:") for value in head: # 隐式调用 iter() 和 next() print(value) # 输出: 1 → 2 → 3 → 4 # 手动使用 next() print("\n手动迭代:") iterator = iter(head) # 调用 __iter__() 返回生成器 print(next(iterator)) # 1 print(next(iterator)) # 2 print(next(iterator)) # 3 print(next(iterator)) # 4 # next(iterator) # 引发 StopIteration ``` ### 实现原理 1. **迭代过程**: ```mermaid graph LR A[调用 iter(head)] --> B[创建生成器对象] B --> C[首次 next():<br>current=head, yield 1] C --> D[移动 current=current.next] D --> E[第二次 next():<br>yield 2] E --> F[...直到 current=None] F --> G[自动引发 StopIteration] ``` 2. **内存效率**: - 不需要额外存储空间($O(1)$ 空间复杂度) - 惰性求值:只在需要时生成下一个值 3. **时间效率**: - 遍历时间复杂度 $O(n)$ - 每次 `next()` 操作为 $O(1)$ ### 进阶应用 **迭代节点对象(而不仅是值)**: ```python def __iter__(self): current = self while current: yield current # 直接返回节点对象 current = current.next # 使用示例 for node in head: print(f"值: {node.val}, 下一节点: {node.next.val if node.next else None}") ``` **处理空链表**: ```python def __iter__(self): if not self: # 检查空链表 return current = self while current: yield current.val current = current.next ``` ### 常见问题解答 1. **为什么不需要显式实现 `__next__`**? - 生成器自动实现迭代器协议 - `yield` 自动处理 `StopIteration`[^1] 2. **能否从中间节点开始迭代**? ```python mid_node = head.next.next for value in mid_node: # 从节点3开始 print(value) # 输出: 3 → 4 ``` 3. **如何修改迭代返回值**? ```python def __iter__(self): current = self while current: yield current.val * 2 # 返回值的两倍 current = current.next ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值