社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

如何使for循环在python中更容易理解?

elias • 5 年前 • 2182 次点击  

我目前正在教一些相当年轻的学生一些python编程。我想让他们学习的一件事是如何编写for循环。

到目前为止,我向学生展示的方式是这样的:

for i in range(1,11):
    print(i)

它给出了一个循环 i 从1到10。

我的问题是学生们觉得奇怪的是他们需要写11作为第二个论点 range(1,11) 当他们希望循环上升到10。学生们觉得这很混乱。

在C/C++和相关语言中,这样的循环可以这样写成:

for(int i = 1; i <= 10; i++)
    { /* do something */ }

在我看来,c++表示循环的方式更直观,因为在这种情况下,我可以显式地编写1和10,这是我希望循环变量采用的第一个和最后一个值。

在python中使用for循环时,我会告诉学生 “我们只需接受,当我们希望循环变为10时,需要写11,这有点烦人,但您只需了解range函数的工作方式” . 我对此不高兴;我希望他们知道编程很有趣,我担心这种事情会让编程变得不那么有趣。

由于python经常被描述为一种强调可读性的语言,我怀疑有一种更好的方式来表示for循环,这种方式可以减少我的学生的困惑。

在python语言中,是否有更好和/或更少混乱的方式来表示这种for循环?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/44193
 
2182 次点击  
文章 [ 14 ]  |  最新文章 5 年前
R.A.Munna
Reply   •   1 楼
R.A.Munna    5 年前

从你的文章中。我认为一切都不能一概而论。各自为政。 程序设计的概念是相同的,但在不同的语言中,它们的表示或语法是不同的。 所以,如果我是你,我会分享这个概念,我会用语言语法来表示这些概念。

因为循环的概念是一样的。 (Initialize, condition, increment/decrement) 如果你想用python来写,那就用python来写。例如。

start, stop, step = 1, 11, 1
for i in range(start, stop, step):
    print(i, end=', ')
# Output: 1 2 3 4 5 6 7 8 9 10 
  • 开始: 序列的起始编号, default=0. (initialize)
  • 停止: 生成最多个数字,但不包括此数字。 (condition)
  • 步骤: 序列中每个数字之间的差异, default=1. (increment/decrement)

其他人的答案中已经给出了python for loop示例。谢谢您。

Marcel Wilson
Reply   •   2 楼
Marcel Wilson    5 年前

我猜孩子们都到了小学年龄,在教学中要记住的是 保持简单 . 一次给他们一点信息。
你想教他们循环吗?教他们 只有 关于for循环。

假设他们知道字符串和列表,可能会出现这种情况:

somelist = ['a', 'b', 'c', 'd', 'e']
for letter in somelist:
    print(letter)
tmozden
Reply   •   3 楼
tmozden    5 年前

python for loops的操作与传统的c风格for loops不同,如前所述 here . 它们的功能更像其他语言或迭代器方法中的“for-each”循环。在您的示例中使用的range函数只是创建要迭代的整数对象集合的一种方便方法。包括“开始”和“停止”的原因总结如下 here 很好。

在向新程序员解释这一点时,我会将其分解并解释for循环如何操作,然后解释如何使用range函数为for循环提供一个迭代集合。

例子: for循环用于为集合中的每个项执行以下代码块:

collection = [1, 2, 3]
for collectionMember in collection:
    print(collectionMember)

接下来解释如何使用range函数创建整数集合。

创建可用于循环的整数集合的一种简单方法是使用range()函数:

collection = range(1,4)
print(collection)
for collectionMember in collection:
   print(collectionMember)

我知道这不是for循环在其他语言中的工作方式,但在我看来,如果你教它们用python编程,那么首先教它们python版本是如何工作的,然后一旦它们牢牢掌握了如何在其他语言中解释循环是如何工作的,以及这是如何工作的,就会更容易。不同的。

amanb
Reply   •   4 楼
amanb    5 年前

我认为计算机科学学习中最重要的概念之一是理解数组索引的工作原理。你应该花点时间用简单的例子向学生解释这个概念。从Lisp开始,几乎 全部的 编程语言以 Zero-based numbering . Python和C++没有什么不同。在python中,简单 lists 可以作为例子来说明这个概念。

#a simple list
In [15]: list1 = [1,2,3,4,5,6,7,8,9,10,11]
In [23]: len(list1) #number of items in the list
Out[23]: 11
In [26]: list1[0] #the first item in the list
Out[26]: 1
In [25]: print("list1 starts at index {}. The number at this index is {}.".format(list1.index(1), list1[0]))
list1 starts at index 0. The number at this index is 1.
In [37]: list1[10] #the last item in the list
Out[37]: 11
In [19]: print("list1 ends at index {}. The number at this index is {}.".format(len(list1)-1, list1[-1]))
list1 ends at index 10. The number at this index is 11.

正如您将观察到的,“number”值在“index”值之前 1 . 如果名单上 list1 以0开始,以11结束,则索引值和“数字”值将相同,但列表中的项目数将增加 这是因为我们包含了0。我们需要这样的想法,请稍等片刻:

In [29]: list2 = [0,1,2,3,4,5,6,7,8,9,10,11]
In [31]: len(list2) #total number of items in list
Out[31]: 12
In [32]: list2[0]
Out[32]: 0
In [35]: list2[11]
Out[35]: 11

记住 range() 根据文件: range(start, end, step) . 我们会忽略的 为了这次讨论。

所以,现在如果我想生成一个类似于 list2 使用 距离() ,我可以使用上面的信息来形成range()的通用语法:

Syntax: range(start, len(list2)+start), where start is the first item in the range, 
        list2 is a list and len(list2) is its size and the end is len(list2) + start

为了将其放入列表中,我只需将上面的作为参数传递给 list() 功能。了解这个函数的本质并不重要,它只用于说明。因此,我们得到:

In [39]: list3 = list(range(0,len(list2)+0))    
In [40]: list3
Out[40]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]    
In [41]: list2 == list3 #both lists are equivalent
Out[41]: True
In [42]: len(list3)
Out[42]: 12          #same number of items as list2
In [46]: for i in range(0,len(list3)+0): #can replace list3 with list2 to get same results
    ...:     print(i, end=' ')
        ...:

0 1 2 3 4 5 6 7 8 9 10 11   #Output         

for循环按索引位置迭代。所以, i 从项目0的索引位置0(范围开始)开始,一直到项目11的索引位置11(范围结束=11+0)。

我们还可以验证上述语法 表1 那有 开始 长度为11。

In [6]: list(range(1,len(list1)+1))
Out[6]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] #same as list1 above
In [15]: for i in range(1,len(list1)+1):
    ...:     print(i, end=' ')
    ...:
1 2 3 4 5 6 7 8 9 10 11

同样,for循环像往常一样从索引位置0开始,该位置有项1(范围的开始),到索引位置10结束,该位置有项11(范围的结束=11+1)。

现在,让我们来看看这个概念如何也适用于C++。我们用同样的方法 表2 有12个项目,即 len(list2) = 12 . 同样,如果学生不太熟悉数组,那么在下面的示例中深入了解所有内容的细节并不重要。这只是为了说明:

#include <iostream>

using namespace std;

int main()
{
    int list2[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
    std::cout << "Length of array list2 = " << (sizeof(list2)/sizeof(*list2)) << std::endl;
    for(int i=0;i<(sizeof(list2)/sizeof(*list2));i++)
    {
        cout<<i<<' ';
    }
    return 0;
}

//Output:
Length of array list2 = 12                                                                                            
0 1 2 3 4 5 6 7 8 9 10 11  #Output

通知 i<(sizeof(list2)/sizeof(*list2)) 确保从数组的上界检索最终项,即从index=12-1=11检索项11。这正是 距离() 函数可以。如果我这样做 i<=(sizeof(list2)/sizeof(*list2)) ,也会在不是 表2 将超出数组的上限。在python中, 距离() 函数对数组边界更加明确。所以,如果我重写 距离() 上面的语法并允许for循环从0迭代到后面的项 表2 通过递增 结束 通过1,我可以显式地打印该项:

In [13]: for i in range(0,len(list2)+1):
    ...:     if i>=len(list2):
    ...:         print("\nI am outside of list2: {}".format(i))
    ...:     else:
    ...:         print(i, end=' ')
    ...:
0 1 2 3 4 5 6 7 8 9 10 11
I am outside of list2: 12

我们从这次讨论中了解到,将循环迭代理解为基于索引的操作和 range(start,end) 是一个python内置函数,它只在开始和结束之间组合值 范围 , 包含起始值,不包含结束值 . 考虑遍历的值的总数,包括 开始 ( len(total) + start ) 结束 范围的。for循环实现与此无关,只考虑python和c++中的索引位置。

J Lossner
Reply   •   5 楼
J Lossner    5 年前

问题不在于理解for循环,而在于理解不包括端点的范围。一种方法是将部分区域视为围栏柱和分段;使用范围(10)构建“围栏”将为您提供一个包含10个围栏的围栏 帖子 =

|-|-|-|-|-|-|-|

但是,你看到的数字是有限度的 部分 ==-你必须在栅栏柱的左边(),那是0-1-2-3-4-5-6-7-8-9

如果添加起点range(1,10),它仍然会使用10个围栏柱构建围栏,但是索引只查看至少有1个围栏段的所有内容,因此第一个围栏柱不属于您的范围。但是当你看到的第一个栅栏柱的索引从0开始时,你会得到1-2-3-4-5-6-7-8-9;仍然没有10,因为我们原来的栅栏只有10个柱长。因此,要么你用11根柱子建造一个围栏,忽略所有小于1段(范围(1,11))的东西,要么你用10根柱子建造一个围栏,并假设在它的左边还有另一段(范围(0,10)+1)。

将步长更改为大于1只意味着您只需从第一个开始计算每2/3/etc栏柱的数量,因此,如果还有更多的栏柱剩余,但没有更多的栏柱可供计算,则最后的其余栏柱将被截断并忽略。

Jonathan Gagne
Reply   •   6 楼
Jonathan Gagne    5 年前

重要的是让他们理解列表和数组总是以0开头的标准方式。为了便于理解,请向他们显示下面的代码,这将很容易理解为什么数组从索引0开始。不要回避复杂性,而要简化它。

for i in range(10):
    i+=1
    print(i)

for i in range(10):
    print(i+1)
Richard K Yu
Reply   •   7 楼
Richard K Yu    5 年前

试试这个:

for i in range(10):
    print(i+1)

list_of_numbers = range(1,11)

for number in list_of_numbers:
    print(number)
imposeren
Reply   •   8 楼
imposeren    5 年前

不是“多”或“少”可以理解,而是你如何描述它:

  • for x in something :迭代来自iterable的值 something 作为变量 x . 所以你需要解释的是 range(...) “。
  • range(start, end,...) 返回从开始(包含)到停止(排除)生成整数序列的对象。给他们看看 help(range)

你问的是“如何使for循环更像c?”

有一些方法可以做到这一点:


def nrange(start, num_elements, step=1):
    """Similar to `range`, but second argument is number of elements."""
    return range(start, start + step*num_elements, step)


def inclusive_range(start_or_stop, stop=None, step=1):
    if stop is None:
        start = 0
        stop = start_or_stop+1
    else:
        start = start_or_stop
        stop = stop + step
    return range(start, stop, step)


_default_update_func = lambda item: item+1
def c_like_iterator(start, test_func, update_func=_default_update_func):
    cur_value = start
    while test_func(cur_value):
        yield cur_value
        cur_value = update_func(cur_value)

for i in nrange(1, 10):
    print(i)

for i in inclusive_range(1, 10):
    print(i)

for i in inclusive_range(10):  # this will give 11 elements because both 0 and 10 values are included
    print(i)

for i in c_like_iterator(1, lambda x: x<=10, lambda x: x+1):
    print(i)

for i in c_like_iterator(1, lambda x: x<11, lambda x: x+1):
    print(i)

for i in inclusive_range(1, -10, -1):
    print(i)

Alain T.
Reply   •   9 楼
Alain T.    5 年前

您的学生将从早期学习中受益,因为大多数编程语言使用基于零的索引。理解python的range()函数最简单的方法是只使用一个参数。

for i in range(10):
    # will iterate exactly 10 times with i going from 0 to 9

在一个零基础的世界里,这是完全有意义的。

python的范围(以区间表示法)有一个独占的上限:[0..[10,而非计算机工程师默认使用的包含区间[1…10]

鉴于此,给range函数的参数被理解为唯一的“stop”值。

当您使用一个额外的参数来提供一个起点时,突然以不同的方式处理停止值是不一致的。这将使range(0,10)的行为与range(10)不同,这将非常令人困惑。

与c的主要区别在于range()表示“小于”比较,而不是“小于或等于”:

 for i in range(A,B):   # for (i=A;i<B;i++)
     ...

你可以给你的学生提供一个“inclusiverange”函数,让他们在不掌握零基础概念的情况下开始学习。

 def inclusiveRange(start=0,end,step=1):
     return range(start,end+1,step)

他们可以用它代替range()

 for i in inclusiveRange(1,10):
     ... # will iterate from 1 to 10 inclusively

缺点是,当学生开始使用列表索引或计算坐标系中的位置时,必须“取消学习”循环。你可以救他们很多 - 1 off by one 在未来,通过现在的零基索引让他们上船。

igrinis
Reply   •   10 楼
igrinis    5 年前

我的问题是,学生们似乎很奇怪,当他们希望循环达到10时,他们需要将11作为范围(1,11)的第二个参数。学生们觉得这很混乱。

混乱不是来自 for 声明,但来自 range . 你需要做的是把你的解释分成两部分:首先 对于 迭代它的参数,而不关心参数的内容。所以

for i in [1,2,3]:
    {*do something*}

用3个元素迭代列表。

现在, 范围 定义为整数的半开区间 a <= x < b 因为这有很多很好的数学性质,比如

len(range(a, b)) == b - a
len(range(a)) == a
range(a, a) == []
range(a, b) + range(b, c) == range(a, c)

如果 范围 将是一个封闭的时间间隔,程序员必须用 -1 到处都是。

This 是一篇关于主题的不错的博客文章。

T Burgis
Reply   •   11 楼
T Burgis    5 年前

向他们展示两个C++变体:

# using <= operator
for(int i = 1; i <= 10; i++)
    { /* do something */ }

# using < operator
for(int i = 1; i < 11; i++)
    { /* do something */ }

告诉他们巨蟒 range 函数的操作与第二个类似。

Saurav Rai
Reply   •   12 楼
Saurav Rai    5 年前

我相信有两种简单的方法来回答这个问题。 1)解释这个答案的一种方法是使用数学符号半闭区间[a,b]。在此间隔中,包含一个端点(在本例中为“a”),但不包括另一个端点(“b”)。 以你为例,

for i in range(1,11):
     print(i)

(1,11)是半闭区间,其中a和b分别为1和11。

2)您还可以使用以下示例进行解释

    for i in range(1,11)  //in python 
        {do something}

    for(int i=1;i<11;i++)  //in C++
        {do something}

在这两种情况下,我从1迭代到10。这在我看来更直观。

soundstripe
Reply   •   13 楼
soundstripe    5 年前

提醒他们range函数这样工作是有原因的。它的一个有用特性是循环将运行的次数等于range的第二个参数减去第一个参数。

我想人们真的很担心这个,但事实是 for python中的循环与c中的非常不同。 对于 循环基本上是一个while循环的包装器。

这两个例子应该有助于说明循环在c和python中是如何工作的。

# for(int x=1; x <= 10; x++)
x = 1
while x <= 10:
    print(x)
    x += 1


i = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  # range(1, 11)
for x in i:
    print(i)

但老实说,这里真正的问题是,如果所有的循环和数组都从零开始,而不是从一开始,那么它们就更容易理解和使用。请考虑调整你的例子,从零开始。

这样,如果你想循环10次,你就用数字10。

   # for(int x=0; x < 10; x++)
x = 0
while x < 10:
    print(x)
    x += 1


i = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  # range(10)
for x in i:
    print(i)
Gábor Fekete
Reply   •   14 楼
Gábor Fekete    5 年前

为了更好地理解,您可以向他们展示以下代码:

start = 1
length = 10
for i in range(start,start+length):
    print(i)

还有一个功能可以像这样工作,叫做 slice .