精华内容
下载资源
问答
  • range()
    千次阅读
    2021-10-07 22:27:13

    大家好,我是peachestao,今天是国庆节的最后一天,大部分人应该都已经返程了,不知道大家这个国庆玩的怎么样。

    前段时间工作有点忙,加上生活中的一些事导致一个月没更新了,以后会加快更新频率。

    分享是一个再学习的过程,不知道大家有没有过这样的体会:某个知识点写之前觉得掌握透了,但是当你写出来的时候发现自己对知识点的理解有盲区,只掌握了个大概,不知道来龙去脉,无法自圆其说。

    秉着”写出来并让大家理解就是自己完全掌握透了的“分享原则,会逼着自己查阅各种资料并亲手实践,在这个过程中你会恍然大悟:”原来如此“。

    分享前的我觉得懂->分享时的疑惑->查阅资料->亲手实践->新的认知,这个过程就是再学习的过程,也是精进的过程。

    话不多说,进入今天的分享主题,for range语句是业务开发中编写频率很高的代码,其中会有一些常见的坑,看完这篇文章会让你少入坑。

    先看一下提纲:

    • for range的基本用法

    • for range和for的区别

    • for range容易踩的坑

    • for range和for性能比较

    • for range的底层原理

    • 总结

    for range基本用法

    range是Golang提供的一种迭代遍历手段,可操作的类型有数组、切片、string、map、channel等

    1、遍历数组

    myArray := [3]int{1, 2, 3}
    for i, ele := range myArray {
        fmt.Printf("index:%d,element:%d\n", i, ele)
        fmt.Printf("index:%d,element:%d\n", i, myArray[i])
    }

    直接取元素或通过下标取

    2、遍历slice

    mySlice := []string{"I", "am", "peachesTao"}
    for i, ele := range mySlice {
        fmt.Printf("index:%d,element:%s\n", i, ele)
        fmt.Printf("index:%d,element:%s\n", i, mySlice[i])
    }

    直接取元素或通过下标取

    3、遍历string

    s:="peachesTao"
    for i,item := range s {
       fmt.Println(string(item))
       fmt.Printf("index:%d,element:%s\n", i, string(s[i]))
    }

    直接取元素或通过下标取

    注意:循环体中string中的元素实际上是byte类型,需要转换为字面字符

    4、遍历map

    myMap := map[int]string{1:"语文",2:"数学",3:"英语"}
    for key,value := range myMap {
        fmt.Printf("key:%d,value:%s\n", key, value)
        fmt.Printf("key:%d,value:%s\n", key, myMap[key])
    }

    直接取元素或通过下标取

    5、遍历channel

    myChannel := make(chan int)
    go func() {
      for i:=0;i<10;i++{
         time.Sleep(time.Second)
         myChannel <- i
      }
    }()
    
    go func() {
     for c := range myChannel {
        fmt.Printf("value:%d\n", c)
     }
    }()

    channel遍历是循环从channel中读取数据,如果channel中没有数据,则会阻塞等待,如果channel已被关闭,则会退出循环。

    for range 和 for的区别

    • for range可以直接访问目标对象中的元素,而for必须通过下标访问

    • for frange可以访问map、channel对象,而for不可以

    for range容易踩的坑

    下面的例子是将mySlice中每个元素的后面都加上字符"-new"

    mySlice := []string{"I", "am", "peachesTao"}
    for _, ele := range mySlice {
        ele=ele+"-new"
    }
    fmt.Println(mySlice)

    结果:

    [I am peachesTao]

    打印mySlice发现元素并没有更新,为什么会这样?

    原因是for range语句会将目标对象中的元素copy一份值的副本,修改副本显然不能对原元素产生影响

    为了证明上述结论,在遍历前和遍历中打印出元素的内存地址

    mySlice := []string{"I", "am", "peachesTao"}
    fmt.Printf("遍历前首元素内存地址:%p\n",&mySlice[0])
    for _, ele := range mySlice {
        ele=ele+"-new"
        fmt.Printf("遍历中元素内存地址:%p\n",&ele)
    }
    fmt.Println(mySlice)

    结果:

    遍历前第一个元素内存地址:0xc000054180
    遍历前第二个元素内存地址:0xc000054190
    遍历前第三个元素内存地址:0xc0000541a0
    遍历中元素内存地址:0xc000010200
    遍历中元素内存地址:0xc000010200
    遍历中元素内存地址:0xc000010200
    [I am peachesTao]

    可以得出两个结论:

    • 遍历体中的元素内存地址已经发生了变化,生成了元素副本,至于产生副本的原因在“for range底层原理”段落中会有介绍

    • 遍历体中的只生成了一个全局的元素副本变量,不是每个元素都会生成一个副本,这个特点也值得大家注意,否则会踩坑。

    比如遍历mySlice元素生成一个[]*string类型的mySliceNew,要通过一个中间变量取中间变量的地址(或者通过下标的形式访问元素也可以)加入mySliceNew,如果直接取元素副本的地址会导致mySliceNew中所有元素都是一样的,如下:

    mySlice := []string{"I", "am", "peachesTao"}
    var mySliceNew []*string
    for _, item := range mySlice {
        itemTemp := item
        mySliceNew = append(mySliceNew, &itemTemp)
        //mySliceNew = append(mySliceNew, &item) 错误的做法
    }

    回到刚才那个问题,如何能在遍历中修改元素呢?答案是直接通过下标访问slice中的元素对其赋值,如下:

    mySlice := []string{"I", "am", "peachesTao"}
    for i, _ := range mySlice {
        mySlice[i] = mySlice[i]+"-new"
    }
    fmt.Println(mySlice)

    结果:

    [I-new am-new peachesTao-new]

    可以看到元素已经被修改

    for range和for性能比较

    我们定义一个结构体Item,包含int类型的id字段,对结构体数组分别使用for、for range item、for range index的方式进行遍历,下面是测试代码(直接引用“Go语言高性能编程”这篇文章中的例子,下面的reference中有链接地址)

    type Item struct {
      id  int
    }
    
    func BenchmarkForStruct(b *testing.B) {
      var items [1024]Item
      for i := 0; i < b.N; i++ {
        length := len(items)
        var tmp int
        for k := 0; k < length; k++ {
          tmp = items[k].id
        }
        _ = tmp
      }
    }
    
    func BenchmarkRangeIndexStruct(b *testing.B) {
      var items [1024]Item
      for i := 0; i < b.N; i++ {
        var tmp int
        for k := range items {
          tmp = items[k].id
        }
        _ = tmp
      }
    }
    
    func BenchmarkRangeStruct(b *testing.B) {
      var items [1024]Item
      for i := 0; i < b.N; i++ {
        var tmp int
        for _, item := range items {
          tmp = item.id
        }
        _ = tmp
      }
    }

    运行基准测试命令:

    go test -bench . test/for_range_performance_test.go

    测试结果:

    goos: darwin
    goarch: amd64
    BenchmarkForStruct-4             3176875               375 ns/op
    BenchmarkRangeIndexStruct-4      3254553               369 ns/op
    BenchmarkRangeStruct-4           3131196               384 ns/op
    PASS
    ok      command-line-arguments  4.775s

    可以看出:

    for range 通过Index和直接访问元素的方式和for的方式遍历性能几乎无差异

    下面我们在Item结构体添加一个byte类型长度为4096的数组字段val

    type Item struct {
      id  int
      val [4096]byte
    }

    再运行一遍基准测试,结果如下:

    goos: darwin
    goarch: amd64
    BenchmarkForStruct-4             2901506               393 ns/op
    BenchmarkRangeIndexStruct-4      3160203               381 ns/op
    BenchmarkRangeStruct-4              1088            948678 ns/op
    PASS
    ok      command-line-arguments  4.317s

    可以看出:

    • for range通过下标遍历元素的性能跟for相差不大

    • for range直接遍历元素的性能比for慢近1000倍

    结论:

    • for range通过下标遍历元素的性能跟for相差不大

    • for range直接遍历元素的性能在元素为小对象的情况下跟for相差不大,在元素为大对象的情况下比for慢很多

    for range的底层原理

    对于for-range语句的实现,可以从编译器源码中找到答案。
    编译器源码gofrontend/go/statements.cc/For_range_statement::do_lower()【链接见下方reference方法中有如下注释。

    // Arrange to do a loop appropriate for the type.  We will produce
    //   for INIT ; COND ; POST {
    //           ITER_INIT
    //           INDEX = INDEX_TEMP
    //           VALUE = VALUE_TEMP // If there is a value
    //           original statements
    //   }
    

    可见range实际上是一个C风格的循环结构。range支持string、数组、数组指针、切片、map和channel类型,对于不同类型有些细节上的差异。

    1、range for slice

    下面的注释解释了遍历slice的过程:

    For_range_statement::lower_range_slice

    // The loop we generate:
    //   for_temp := range
    //   len_temp := len(for_temp)
    //   for index_temp = 0; index_temp < len_temp; index_temp++ {
    //           value_temp = for_temp[index_temp]
    //           index = index_temp
    //           value = value_temp
    //           original body
    //   }
    

    遍历slice前会先获得slice的长度len_temp作为循环次数,循环体中,每次循环会先获取元素值,如果for-range中接收index和value的话,则会对index和value进行一次赋值,这就解释了对大元素进行遍历会影响性能,因为大对象赋值会产生gc

    由于循环开始前循环次数就已经确定了,所以循环过程中新添加的元素是没办法遍历到的。

    另外,数组与数组指针的遍历过程与slice基本一致,不再赘述。

    2、range for map 

    下面的注释解释了遍历map的过程:

    For_range_statement::lower_range_map

    // The loop we generate:
    //   var hiter map_iteration_struct
    //   for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
    //           index_temp = *hiter.key
    //           value_temp = *hiter.val
    //           index = index_temp
    //           value = value_temp
    //           original body
    //   }
    

    遍历map时没有指定循环次数,循环体与遍历slice类似。由于map底层实现与slice不同,map底层使用hash表实现,插入数据位置是随机的,所以遍历过程中新插入的数据不能保证遍历到。

    3、range for channel

    遍历channel是最特殊的,这是由channel的实现机制决定的:

    For_range_statement::lower_range_channel

    // The loop we generate:
    //   for {
    //           index_temp, ok_temp = <-range
    //           if !ok_temp {
    //                   break
    //           }
    //           index = index_temp
    //           original body
    //   }
    

    一直循环读数据,如果有数据则取出,如果没有则阻塞,如果channel被关闭则退出循环

    注:

    • 上述注释中index_temp实际上描述是有误的,应该为value_temp,因为index对于channel是没有意义的。

    总结

    • 使用index,value接收range返回值会产生一次数据拷贝,视情况考虑不接收,以提高性能

    • for-range的实现实际上是C风格的for循环

    参考资料

    【《Go专家编程》Go range实现原理及性能优化剖析 https://my.oschina.net/renhc/blog/2396058

    【面试官:用过go中的for-range吗?这几个问题你能解释一下原因吗?】https://zhuanlan.zhihu.com/p/217987219

    【Go语言高性能编程】https://geektutu.com/post/hpg-range.html

    【gofrontend】https://github.com/golang/gofrontend/blob/master/go/statements.cc

    更多相关内容
  • Python中的range函数

    千次阅读 2021-11-09 23:58:01
    每一个Python初学者都一定在开始学Python不久就一定会遇到”range函数“,大家都把他叫做“range函数”,是因为我们在用它的时候像调用函数一样,只需要给它传入参数,它就可以给出你想要的结果。这一点和函数是一样...

    大家好,我是翔宇!今天我们聊聊Python中很重要的range对象!(本文章基于Python3环境,Python2环境下的range会有所不同,但并不影响我们使)

    range对象

    1.range对象是什么

    每一个Python初学者都一定在开始学Python不久就一定会遇到”range函数“,大家都把他叫做“range函数”,是因为我们在用它的时候像调用函数一样,只需要给它传入参数,它就可以给出你想要的结果。这一点和函数是一样的,于是大家就习惯上把它叫做函数。但其实它并不是一个函数,因为它是惰性的,什么叫惰性的呢?给大家看看

    print(range(1,3))    # 如果它是函数,得到的结果是0,1,2,然而
    

    image-20211109201203024

    于是,大家恍然大悟,”它是迭代器“,一开始我也以为是,但是后面才知道,这家伙没那么简单,哪里不简单呢?我们来看看迭代器长啥样。比如迭代器zip

    image-20211109201212576

    并且种种表现也证明了它并不是一个迭代器,“迭代器是惰性的一次性可迭代对象”,也就是说,我们在迭代器是遍历一个元素就少一个,但是它不是,甚至,我们可以对它进行索引(jupyter notebook环境)

    image-20211109201220789

    那么,它到底是什么呢?如果实在要给它一个名字,可以称它为“懒序列”,也就是说,实际上它就是列表元组集合一类的东西,然而,它比较”懒“,那么什么叫懒呢?这里我需要讲一下。为了好理解,我用简单的例子比喻,我知道你们也不想看定义。

    补充:

    懒惰机制在计算机中就是说在为了缓解内存的压力,我们设置懒惰机制不要将计算的结果一次给出,而是在计算机使用者(可以是人也可以是其他机器)需要时再通过计算给出其需要的计算结果。现在再看看迭代器,实际上迭代器就是这样一个惰性机制。不会像列表这样的可迭代对象一次给出所有计算结果。range对象也有这样的特性。

    2.基本语法

    实际上range对象是什么并不是那么的那么的重要,而怎样用它才是我们最应该重点关注的。基本语法

    这是它的使用说明,如果看不懂没有关系!看不懂才有我的用武之地

    image-20211109202935269

    range(start,stop[,step])      # []代表不是必须
    

    参数说明:

    start 默认为0,与stop配合使用,用来指定迭代范围的开始

    例如

    迭代range(5)得到的是

    0,1,2,3,4 表示从0到4 start和stop表示的范围规则:“前闭后开”(也就是说取不到stop)

    stop 与start配合使用,指定迭代范围的结束(并不包括stop本身)

    例如

    迭代range(1,5)得到的是

    1,2,3,4 表示从1到4

    step 步长,默认为1,表示迭代时的增量(或减量),在使用step时必须要指定第一个参数start

    例如

    迭代range(1,5,2) ,得到

    1,3 得到1和3,并不会得到5,因为“前闭后开”,而步长为2,代表取出规则是“取一个元素跳过一个元素再接着取

    3.应用举例

    简单知道range对象的语法以后,我们进行应用举例。

    最常用组合----for循环。不知道的请看我上一遍文章

    插入链接

    我们在上面已经讲到range对象是一个“懒序列”,那么通常我们需要将里面的元素取出来使用。因此,最常用的便是与for 循环配合使用。直接上例子。

    1、stop指定范围结束,start默认为0,stop步长默认为1

    for i in range(9):    # 此时9是stop,指定范围结束,start默认为0,stop步长默认为1
        print(i)
    

    image-20211109205802985

    2、指定start、stop,默认stop

    for i in range(2,9):   
        print(i)
    

    image-20211109210124940

    3、指定stop,此时start和stop不能省略

    for i in range(2,9,2):
        print(i)
    

    image-20211109210316016

    4、stop为负数,此时start可以大于stop,例如

    for i in range(9,2,-2):   # 从9到2,步长为-2,没迭代一次增加-2,即下降2
        print(i)
    

    image-20211109210714944

    思考:如果我们执行以下代码,能得到什么?,还是报错?

    x for i in range(9,2):   
        print(i)
    

    单独使用:

    1、独自打印

    image-20211109211033971

    2.索引

    image-20211109211158776

    思考:那么可以切片吗?如果可以,又会得到怎样的结果呢?

    4.总结

    1、range对象的使用和理解都不难,但是在python的使用中非常常用!

    2、range对象既不是函数也不是迭代器,可以叫它“懒序列”

    3、参数解释:start为范围开始,stop为范围结束,stop为步长

    4、range对象经常和for循环配合使用

    5、可以对range对象进行索引

    好了,今天的内容就分享到这里,我们明天见!

    如果对你有帮助,不要忘记分享给好朋友哦!关注我,防止错过更多内容!
    Python中的range函数

    大家好,我是翔宇!今天我们聊聊Python中很重要的range对象!(本文章基于Python3环境,Python2环境下的range会有所不同,但并不影响我们使)

    range对象

    1.range对象是什么

    每一个Python初学者都一定在开始学Python不久就一定会遇到”range函数“,大家都把他叫做“range函数”,是因为我们在用它的时候像调用函数一样,只需要给它传入参数,它就可以给出你想要的结果。这一点和函数是一样的,于是大家就习惯上把它叫做函数。但其实它并不是一个函数,因为它是惰性的,什么叫惰性的呢?给大家看看

    print(range(1,3))    # 如果它是函数,得到的结果是0,1,2,然而
    

    image-20211109201203024

    于是,大家恍然大悟,”它是迭代器“,一开始我也以为是,但是后面才知道,这家伙没那么简单,哪里不简单呢?我们来看看迭代器长啥样。比如迭代器zip

    image-20211109201212576

    并且种种表现也证明了它并不是一个迭代器,“迭代器是惰性的一次性可迭代对象”,也就是说,我们在迭代器是遍历一个元素就少一个,但是它不是,甚至,我们可以对它进行索引(jupyter notebook环境)

    image-20211109201220789

    那么,它到底是什么呢?如果实在要给它一个名字,可以称它为“懒序列”,也就是说,实际上它就是列表元组集合一类的东西,然而,它比较”懒“,那么什么叫懒呢?这里我需要讲一下。为了好理解,我用简单的例子比喻,我知道你们也不想看定义。

    补充:

    懒惰机制在计算机中就是说在为了缓解内存的压力,我们设置懒惰机制不要将计算的结果一次给出,而是在计算机使用者(可以是人也可以是其他机器)需要时再通过计算给出其需要的计算结果。现在再看看迭代器,实际上迭代器就是这样一个惰性机制。不会像列表这样的可迭代对象一次给出所有计算结果。range对象也有这样的特性。

    2.基本语法

    实际上range对象是什么并不是那么的那么的重要,而怎样用它才是我们最应该重点关注的。基本语法

    这是它的使用说明,如果看不懂没有关系!看不懂才有我的用武之地

    image-20211109202935269

    range(start,stop[,step])      # []代表不是必须
    

    参数说明:

    start 默认为0,与stop配合使用,用来指定迭代范围的开始

    例如

    迭代range(5)得到的是

    0,1,2,3,4 表示从0到4 start和stop表示的范围规则:“前闭后开”(也就是说取不到stop)

    stop 与start配合使用,指定迭代范围的结束(并不包括stop本身)

    例如

    迭代range(1,5)得到的是

    1,2,3,4 表示从1到4

    step 步长,默认为1,表示迭代时的增量(或减量),在使用step时必须要指定第一个参数start

    例如

    迭代range(1,5,2) ,得到

    1,3 得到1和3,并不会得到5,因为“前闭后开”,而步长为2,代表取出规则是“取一个元素跳过一个元素再接着取

    3.应用举例

    简单知道range对象的语法以后,我们进行应用举例。

    最常用组合----for循环。不知道的请看我上一遍文章

    插入链接

    我们在上面已经讲到range对象是一个“懒序列”,那么通常我们需要将里面的元素取出来使用。因此,最常用的便是与for 循环配合使用。直接上例子。

    1、stop指定范围结束,start默认为0,stop步长默认为1

    for i in range(9):    # 此时9是stop,指定范围结束,start默认为0,stop步长默认为1
        print(i)
    

    image-20211109205802985

    2、指定start、stop,默认stop

    for i in range(2,9):   
        print(i)
    

    image-20211109210124940

    3、指定stop,此时start和stop不能省略

    for i in range(2,9,2):
        print(i)
    

    image-20211109210316016

    4、stop为负数,此时start可以大于stop,例如

    for i in range(9,2,-2):   # 从9到2,步长为-2,没迭代一次增加-2,即下降2
        print(i)
    

    image-20211109210714944

    思考:如果我们执行以下代码,能得到什么?,还是报错?

    x for i in range(9,2):   
        print(i)
    

    单独使用:

    1、独自打印

    image-20211109211033971

    2.索引

    image-20211109211158776

    思考:那么可以切片吗?如果可以,又会得到怎样的结果呢?

    4.总结

    1、range对象的使用和理解都不难,但是在python的使用中非常常用!

    2、range对象既不是函数也不是迭代器,可以叫它“懒序列”

    3、参数解释:start为范围开始,stop为范围结束,stop为步长

    4、range对象经常和for循环配合使用

    5、可以对range对象进行索引

    好了,今天的内容就分享到这里,我们明天见!

    如果对你有帮助,不要忘记分享给好朋友哦!关注我,防止错过更多内容!
    也欢迎大家移步到翔宇的公众号“Python和数据分析”阅读更多内容!

    参考:(2条消息) python中的range对象_Python:range 对象并不是迭代器_weixin_39804335的博客-CSDN博客

    展开全文
  • 对应博客:http://blog.csdn.net/u013347241/article/details/51560290
  • range函数pythonPython’s built-in range function is a handy tool to know you need to perform an action a specific number of times. Python的内置range函数是一种方便的工具,可以知道您需要执行特定次数的...

    range函数python

    Python’s built-in range function is a handy tool to know you need to perform an action a specific number of times.

    Python的内置range函数是一种方便的工具,可以知道您需要执行特定次数的操作。

    By the end of this article, you’ll:

    到本文结尾,您将:

    • Understand how Python’s range function works
    • Know how the implementations differ in Python 2 and Python 3
    • Have seen a number of hands-on range() examples
    • Be equipped to work around some of its limitations
    • 了解Python的range函数如何工作
    • 了解Python 2和Python 3中的实现方式有何不同
    • 看到了许多动手的range()示例
    • 有能力克服一些局限性

    Let’s get cracking!

    让我们开始吧!

    Free Bonus: Click here to get our free Python Cheat Sheet that shows you the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.

    免费红利: 单击此处可获得我们的免费Python备忘单 ,其中显示了Python 3的基础知识,例如使用数据类型,字典,列表和Python函数。

    range()的历史 (The History of range())

    Although range() in Python 2 and range() in Python 3 may share a name, they are entirely different animals. In fact, range() in Python 3 is just a renamed version of a function that is called xrange in Python 2.

    虽然range()在Python 2和range()在Python 3可以共享一个名字,它们是完全不同的动物。 实际上,Python 3中的range()只是该函数的重命名版本,在Python 2中称为xrange

    Originally, both range() and xrange() produced numbers that could be iterated over with for-loops, but the former generated a list of those numbers all at once while the latter produced numbers lazily, meaning numbers were returned one at a time as they were needed.

    最初, range()xrange()生成可以用for循环迭代的数字,但是前者一次生成所有这些数字的列表,而后者则懒惰地生成数字,这意味着数字一次返回一个他们是需要的。

    Having huge lists hang around takes up memory, so it’s no surprise that xrange() replaced range(), name and all. You can read more about this decision and the xrange() vs range() background in PEP 3100.

    闲逛着巨大的清单会占用内存,因此xrange()取代了range() ,name和all不足为奇。 您可以在PEP 3100中阅读有关此决定以及xrange()range()背景的更多信息。

    Note: PEP stands for Python Enhancement Proposal. PEPs are documents that can cover a wide range of topics, including proposed new features, style, governance, and philosophy.

    注意: PEP代表Python增强建议。 PEP是可以涵盖广泛主题的文档,包括建议的新功能,样式,治理和理念。

    There are a ton of them. PEP 1 explains how they work and is a great place to start.

    他们有很多。 PEP 1解释了它们如何工作,是一个很好的起点。

    For the rest of this article, you’ll be using the function as it exists in Python 3.

    在本文的其余部分,您将使用Python 3中存在的函数。

    Here we go!

    开始了!

    让我们循环 (Let’s Loop)

    Before we dive into seeing how range() works, we need to take a look at how looping works. Looping is a key computer science concept. If you want to be a good programmer, mastering loops is among the first steps you need to take.

    在深入研究range()工作原理之前,我们需要看一下循环的工作原理。 循环是计算机科学关键概念 。 如果您想成为一名优秀的程序员,那么掌握循环就是您需要采取的第一步。

    Here’s an example of a for-loop in Python:

    这是Python中for循环的示例:

     captains captains = = [[ 'Janeway''Janeway' , , 'Picard''Picard' , , 'Sisko''Sisko' ]
    
    ]
    
    for for captain captain in in captainscaptains :
        :
        printprint (( captaincaptain )
    )
    

    The output looks like this:

    输出看起来像这样:

    As you can see, a for-loop enables you to execute a specific block of code however many times you want. In this case, we looped through a list of captains and printed each of their names.

    如您所见,for循环使您可以执行任意次数的特定代码块。 在这种情况下,我们循环浏览了一系列队长并打印了他们的每个名字。

    Although Star Trek is great and everything, you may want to do more than simply loop through a list of captains. Sometimes, you just want to execute a block of code a specific number of times. Loops can help you do that!

    尽管《星际迷航》非常出色,但您可能要做的不只是简单地浏览一系列队长。 有时,您只想执行一段特定次数的代码。 循环可以帮助您做到这一点!

    Try the following code with numbers that are divisible by three:

    尝试使用下面的代码将其数字除以三:

     numbers_divisible_by_three numbers_divisible_by_three = = [[ 33 , , 66 , , 99 , , 1212 , , 1515 ]
    
    ]
    
    for for num num in in numbers_divisible_by_threenumbers_divisible_by_three :
        :
        quotient quotient = = num num / / 3
        3
        printprint (( "" {}{}  divided by 3 is  divided by 3 is  {}{} ."." .. formatformat (( numnum , , intint (( quotientquotient )))
    )))
    

    The output of that loop will look like this:

    该循环的输出将如下所示:

    That’s the output we wanted, so the loop got the job done adequately, but there is another way to get the same result by using range().

    这就是我们想要的输出,因此循环充分完成了工作,但是还有另一种方法可以通过使用range()获得相同的结果。

    Note: That last code example had some string formatting. To learn more on that topic, you can check out Python String Formatting Best Practices and Python 3’s f-Strings: An Improved String Formatting Syntax (Guide).

    注意:最后一个代码示例具有一些字符串格式。 要了解有关该主题的更多信息,可以查看Python字符串格式化最佳实践Python 3的f字符串:改进的字符串格式化语法(指南)

    Now that you’re more familiar with loops, let’s see how you can use range() to simplify your life.

    现在您对循环更加熟悉了,让我们看看如何使用range()简化生活。

    range()入门 (Getting Started With range())

    So how does Python’s range function work? In simple terms, range() allows you to generate a series of numbers within a given range. Depending on how many arguments you pass to the function, you can decide where that series of numbers will begin and end as well as how big the difference will be between one number and the next.

    那么Python的range函数如何工作? 简单来说, range()允许您在给定范围内生成一系列数字。 根据传递给函数的参数数量,您可以确定该系列数字在何处开始和结束以及一个数字与下一个数字之间的差值有多大。

    Here’s a sneak peek of range() in action:

    这是一个作用range()偷看:

     for for i i in in rangerange (( 33 , , 1616 , , 33 ):
        ):
        quotient quotient = = i i / / 3
        3
        printprint (( "" {}{}  divided by 3 is  divided by 3 is  {}{} ."." .. formatformat (( ii , , intint (( quotientquotient )))
    )))
    

    In this for-loop, you were able to simply create a range of numbers that are divisible by 3, so you didn’t have to provide each of them yourself.

    在此for循环中,您可以简单地创建一个可被3整除的数字范围,因此您不必自己提供每个数字。

    Note: While this example shows an appropriate use of range(), it’s usually frowned upon to use range() too often in for-loops.

    注意:虽然此示例显示了range()的适当用法,但在for循环中经常不建议使用range()

    For example, the following use of range() would generally be considered not Pythonic:

    例如,以下range()使用通常被认为不是Pythonic:

    range() is great for creating iterables of numbers, but it’s not the best choice when you need to iterate over data that could be looped over with the in operator.

    range()非常适合创建数字的可迭代变量,但是当您需要迭代可能用in运算符循环的数据时,它不是最佳选择。

    If you want to know more, check out How to Make Your Python Loops More Pythonic.

    如果您想了解更多信息,请查看如何使Python循环更Pythonic

    There are three ways you can call range():

    您可以通过三种方式调用range()

    1. range(stop) takes one argument.
    2. range(start, stop) takes two arguments.
    3. range(start, stop, step) takes three arguments.
    1. range(stop)采用一个参数。
    2. range(start, stop)有两个参数。
    3. range(start, stop, step)采用三个参数。

    range(stop) (range(stop))

    When you call range() with one argument, you will get a series of numbers that starts at 0 and includes every whole number up to, but not including, the number you have provided as the stop.

    当使用一个参数调用range()时,您将获得一系列从0开始的数字,包括从(直到但不包括)作为stop提供的数字的所有整数。

    Here’s what that looks like in practice:

    这是实际的情况:

     for for i i in in rangerange (( 33 ):
        ):
        printprint (( ii )
    )
    

    The output of your loop will look like this:

    循环的输出将如下所示:

    That checks out: we have all the whole numbers from 0 up to but not including 3, the number you provided as the stop.

    可以检查出:我们拥有从0到但不包括3 (您提供为stop数字)的所有整数。

    range(start, stop) (range(start, stop))

    When you call range() with two arguments, you get to decide not only where the series of numbers stops but also where it starts, so you don’t have to start at 0 all the time. You can use range() to generate a series of numbers from A to B using a range(A, B). Let’s find out how to generate a range starting at 1.

    当您使用两个参数调用range()时,不仅要决定一系列数字的终止位置,而且还要决定其起始位置,因此不必始终从0开始。 您可以使用range()使用range(A, B)生成从A到B的一系列数字。 让我们了解如何生成从1开始的范围。

    Try calling range() with two arguments:

    尝试使用两个参数调用range()

     for for i i in in rangerange (( 11 , , 88 ):
        ):
        printprint (( ii )
    )
    

    Your output will look like this:

    您的输出将如下所示:

    So far, so good: you have all the whole numbers from 1 (the number you provided as the start) up to but not including 7 (the number you provided as the stop).

    到目前为止,一切都很好:你必须从所有整数1 (将你作为提供的号码start了),但不包括7 (你的提供的号码stop )。

    But if you add one more argument, then you’ll be able to reproduce the output you got earlier when you were using the list named numbers_divisible_by_three.

    但是,如果再添​​加一个参数,则将能够重现您在使用名为numbers_divisible_by_three的列表时获得的输出。

    range(start, stop, step) (range(start, stop, step))

    When you call range() with three arguments, you can choose not only where the series of numbers will start and stop but also how big the difference will be between one number and the next. If you don’t provide a step, then range() will automatically behave as if the step is 1.

    当使用三个参数调用range()时,您不仅可以选择一系列数字的起始和终止位置,还可以选择一个数字与下一个数字之间的差值。 如果您不提供step ,则range()将自动表现为step1

    Note: step can be a positive number or a negative number, but it can’t be 0:

    注意: step可以是正数或负数,但不能为0

    >>>
    >>> range(1, 4, 0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: range() arg 3 must not be zero
    
    
    >>>

    If you try to use 0 as your step, then you’ll get an error.

    如果尝试将0用作步骤,则会收到错误消息。

    Now that you know how to use step, you can finally revisit that loop we saw earlier with division by 3.

    现在,您知道如何使用step ,您终于可以重新访问我们之前看到的除以3循环。

    Try it for yourself:

    自己尝试:

     for for i i in in rangerange (( 33 , , 1616 , , 33 ):
        ):
        quotient quotient = = i i / / 3
        3
        printprint (( "" {}{}  divided by 3 is  divided by 3 is  {}{} ."." .. formatformat (( ii , , intint (( quotientquotient )))
    )))
    

    Your output will look exactly like the output of the for-loop you saw earlier in this article, when you were using the list named numbers_divisible_by_three:

    您的输出看起来与您在本文前面看到的for循环的输出完全相同,当您使用名为numbers_divisible_by_three的列表numbers_divisible_by_three

    As you see in this example, you can use the step argument to increase towards a higher number. That’s called incrementing.

    如本例所示,您可以使用step参数将其增加到更大的数字。 这就是所谓的增量。

    随着range()递增 (Incrementing With range())

    If you want to increment, then you need step to be a positive number. To get an idea of what this means in practice, type in the following code:

    如果要递增,则需要将step设为正数。 要了解这实际上意味着什么,请输入以下代码:

     for for i i in in rangerange (( 33 , , 100100 , , 2525 ):
        ):
        printprint (( ii )
    )
    

    If your step is 25, then the output of your loop will look like this:

    如果您的step25 ,那么循环的输出将如下所示:

    You got a range of numbers that were each greater than the preceding number by 25, the step you provided.

    您得到的数字范围比上一个数字大25 ,即您提供的step

    Now that you’ve seen how you can step forwards through a range, it’s time to see how you can step backwards.

    既然您已经了解了如何前进一个范围,那么现在该看看如何后退了。

    range()递减 (Decrementing With range())

    If your step is positive, then you move through a series of increasing numbers and are incrementing. If your step is negative, then you move through a series of decreasing numbers and are decrementing. This allows you to go through the numbers backwards.

    如果您的step是肯定的,那么您将经历一系列递增的数字并且正在递增。 如果step为负,则您将经历一系列递减的数字并递减。 这使您可以倒转数字。

    In the following example, your step is -2. That means that you’ll be decrementing by 2 for each loop:

    在以下示例中,您的step-2 。 这意味着您将为每个循环递减2

     for for i i in in rangerange (( 1010 , , -- 66 , , -- 22 ):
        ):
        printprint (( ii )
    )
    

    The output of your decrementing loop will look like this:

    递减循环的输出将如下所示:

    You got a range of numbers that were each smaller than the preceding number by 2, the absolute value of the step you provided.

    您得到的数字范围均比上一个数字小2 ,即您提供的step绝对值

    The most Pythonic way to create a range that decrements is to use range(start, stop, step). But Python does have a built-in reversed function. If you wrap range() inside reversed(), then you can print the integers in reverse order.

    创建范围减小的最Pythonic方法是使用range(start, stop, step) 。 但是Python确实具有内置的reversed功能。 如果将range()包装在reversed() ,则可以按相反的顺序打印整数。

    Give this a try:

    试试看:

     for for i i in in reversedreversed (( rangerange (( 55 )):
        )):
        printprint (( ii )
    )
    

    You’ll get this:

    您将获得:

    range() makes it possible to iterate over a decrementing sequence of numbers, whereas reversed() is generally used to loop over a sequence in reverse order.

    range()可以迭代递减的数字序列,而reversed()通常用于以相反顺序循环序列。

    Note: reversed() also works with strings. You can learn more about the functionality of reversed() with strings in How to Reverse a String in Python.

    注意: reversed()也适用于字符串。 您可以在如何在Python中反转字符串中了解有关带有字符串的reversed()功能的更多信息。

    使用range()更深入 (Going Deeper With range())

    Now that you know the basics of how to use range(), it’s time to dig a little deeper.

    现在,您已经知道如何使用range()的基础知识,是时候进行更深入的研究了。

    range() is mainly used for two purposes:

    range()主要用于两个目的:

    1. Executing the body of a for-loop a specific number of times
    2. Creating more efficient iterables of integers than can be done using lists or tuples
    1. 执行for循环的主体特定次数
    2. 比使用列表或元组创建更有效的整数可迭代

    The first use is probably the most common, and you could make the case that itertools gives you a more efficient way to construct iterables than range() does.

    第一次使用可能是最常见的用法,并且可以证明itertools为您提供了比range()更有效的构造可迭代对象的方法。

    Here are a few more points to keep in mind when you use range.

    使用范围时,请记住以下几点。

    range() is a type in Python:

    range()是Python中的一种类型:

    >>>
    >>> type(range(3))
    <class 'range'>
    
    
    >>>

    You can access items in a range() by index, just as you would with a list:

    您可以按索引访问range()的项目,就像使用列表一样:

    >>>
    >>> range(3)[1]
    1
    >>> range(3)[2]
    2
    
    
    >>>

    You can even use slicing notation on a range(), but the output in a REPL may seem a little strange at first:

    您甚至可以在range()上使用切片符号,但是REPL的输出乍一看似乎有些奇怪:

    >>>
    >>> range(6)[2:5]
    range(2, 5)
    
    
    >>>

    Although that output may look odd, slicing a range() just returns another range().

    尽管该输出可能看起来很奇怪,但是切片range()只会返回另一个range()

    The fact that you can access elements of a range() by index and slice a range() highlights an important fact: range() is lazy, unlike a list, but isn’t an iterator.

    您可以访问一个元素的事实range()通过索引和分割一个range()突出了一个重要的事实: range()是懒惰的,不像一个列表,但不是一个迭代器

    浮点数和range() (Floats and range())

    You may have noticed that all of the numbers we have been dealing with so far have been whole numbers, which are also called integers. That’s because range() can take only integers as arguments.

    您可能已经注意到,到目前为止,我们一直在处理的所有数字都是整数,也称为整数。 这是因为range()只能接受整数作为参数。

    浮游物语 (A Word on Floats)

    In Python, if a number is not a whole number, then it is a float. There are some differences between integers and floats.

    在Python中,如果数字不是整数,则为浮点数。 整数和浮点数之间有一些区别。

    An integer (int data type):

    整数( int数据类型):

    • Is a whole number
    • Does not include a decimal point
    • Can be positive, negative, or 0
    • 是整数
    • 不包含小数点
    • 可以为正,负或0

    A floating point number (float data type):

    浮点数( float数据类型):

    • Can be any number that includes a decimal point
    • Can be positive or negative
    • 可以是任何包含小数点的数字
    • 可以是正数或负数

    Try calling range() with a float and see what happens:

    尝试用浮点数调用range() ,看看会发生什么:

     for for i i in in rangerange (( 3.33.3 ):
        ):
        printprint (( ii )
    )
    

    You should get the following error message:

    您应该收到以下错误信息:

    If you need to find a workaround that will allow you to use floats, then you can use NumPy.

    如果需要找到一种允许使用浮点数的解决方法,则可以使用NumPy。

    使用NumPy (Using NumPy)

    NumPy is a third-party Python library. If you are going to use NumPy, your first step is to check if you have it installed.

    NumPy是第三方Python库。 如果要使用NumPy,则第一步是检查是否已安装它。

    Here’s how you can do that in your REPL:

    您可以在REPL中执行以下操作:

    >>>
    >>> import numpy
    
    
    >>>

    If you get a ModuleNotFoundError, then you need to install it. To do so, go to your command line and enter pip install numpy.

    如果收到ModuleNotFoundError ,则需要安装它。 为此,请转到命令行并输入pip install numpy

    Once you have it installed, put in the following:

    安装完成后,放入以下内容:

     import import numpy numpy as as np
    
    np
    
    npnp .. arangearange (( 0.30.3 , , 1.61.6 , , 0.30.3 )
    )
    

    It will return this:

    它将返回此:

    If you want to print each number on its own line, you can do the following:

    如果要在每个行上打印每个数字,可以执行以下操作:

     import import numpy numpy as as np
    
    np
    
    for for i i in in npnp .. arangearange (( 0.30.3 , , 1.61.6 , , 0.30.3 ):
        ):
        printprint (( ii )
    )
    

    This is the output:

    这是输出:

    Where did 0.8999999999999999 come from?

    0.8999999999999999来自哪里?

    Computers have trouble saving decimal floating-point numbers in binary floating-point numbers. This leads to all sorts of unexpected representations of numbers.

    计算机在将十进制浮点数保存为二进制浮点数时遇到了麻烦。 这导致各种意外的数字表示。

    Note: To learn more about why there are issues representing decimals, you can check out this article and the Python docs.

    注意:要了解有关为何存在代表小数的问题的更多信息,可以查看本文Python文档

    You might also want to take a look at the decimal library, which is a bit of a downgrade in terms of performance and readability but allows you to represent decimal numbers exactly.

    您可能还想看一下十进制库 ,它在性能和可读性方面有些降级,但允许您精确地表示十进制数。

    Another option is to use round(), which you can read more about in How to Round Numbers in Python. Keep in mind that round() has its own quirks that might generate some surprising results!

    另一种选择是使用round() ,您可以在如何在Python中对数字进行四舍五入中了解更多信息。 请记住, round()有其自身的怪癖,可能会产生一些令人惊讶的结果!

    Whether or not these floating point errors are an issue for you depends on the problem you’re solving. The errors are going to be in something like the 16th decimal place, which is insignificant most of the time. They are so small that, unless you’re working on calculating satellite orbital trajectories or something, you don’t need to worry about it.

    这些浮点错误是否对您来说是一个问题,取决于您要解决的问题。 错误将在小数点后第16位出现,这在大多数情况下是微不足道的。 它们是如此之小,除非您正在计算卫星轨道轨迹或其他东西,否则您不必担心。

    Alternatively, you could also use np.linspace(). It does essentially the same thing but uses different parameters. With np.linspace(), you specify start and end (both inclusive) as well as the length of the array (instead of step).

    另外,您也可以使用np.linspace() 。 它实际上执行相同的操作,但是使用不同的参数。 使用np.linspace() ,您可以指定startend (包括两端)和数组的长度(而不是step )。

    For instance, np.linspace(1, 4, 20) gives 20 equally spaced numbers: 1.0, ..., 4.0. On the other hand, np.linspace(0, 0.5, 51) gives 0.00, 0.01, 0.02, 0.03, ..., 0.49, 0.50.

    例如, np.linspace(1, 4, 20)给出20个等间距的数字: 1.0, ..., 4.0 。 在另一方面, np.linspace(0, 0.5, 51)赋予0.00, 0.01, 0.02, 0.03, ..., 0.49, 0.50

    Note: To learn more, you can read Look Ma, No For-Loops: Array Programming With NumPy and this handy NumPy reference.

    注意:要了解更多信息,您可以阅读Look Ma,No For-Loops:使用NumPy进行数组编程以及此便捷的NumPy参考

    前进并循环 (Go Forth and Loop)

    You now understand how to use range() and work around its limitations. You also have an idea of how this important function has evolved between Python 2 and Python 3.

    现在,您了解了如何使用range()并解决其局限性。 您还应该了解此重要功能在Python 2和Python 3之间如何演变。

    The next time you need to perform an action a specific number of times, you’ll be all set to loop your heart out!

    下次您需要执行特定次数的操作时,一切都准备好了!

    Happy Pythoning!

    快乐的Pythoning!

    翻译自: https://www.pybloggers.com/2018/10/pythons-range-function-guide/

    range函数python

    展开全文
  • 理解Range对象

    千次阅读 2019-07-02 19:43:56
    1.理解Range对象 重新来学习下HTML5中的Range对象和Selection对象,最近在维护富文本编辑器,感觉这方面的知识点很有用,所以趁着周末多学习下~ 什么是Range对象? 在HTML5中,一个Range对象代表页面上的一段连续...

    1.理解Range对象

    重新来学习下HTML5中的Range对象和Selection对象,最近在维护富文本编辑器,感觉这方面的知识点很有用,所以趁着周末多学习下~

    什么是Range对象?
    在HTML5中,一个Range对象代表页面上的一段连续区域。可以通过如下语句创建一个空的Range对象。如下代码:

    var range = document.createRange();
    

    什么是Selection对象?
    在HTML5中,每一个浏览器窗口都有一个Selection对象,代表用户鼠标在页面中所选取的区域。可以通过如下代码得到一个Selection对象:

    var selection = window.getSelection();
    或 
    var selection = document.getSelection();
    

    Selection对象与Range对象的区别是?
    每一个Selection对象都有一个或多个Range对象,每一个Range对象代表用户用鼠标所选取范围内的一段连续区域。

    Firefox 与 chrome,safari对Selection的区别?
    在Firefox浏览器中,用户可以通过按住 ctrl键来选取页面上的多个区域,因此一个Selection对象可能有多个Range对象。
    在chrome或safari浏览器中,用户每次只能选取一段区域,所以一个Selection对象中只能有一个Range对象。

    如何获取Selection对象中的某个Range对象呢?
    可以通过Selection对象的getRangeAt方法来获取。代码如下:

    var range = document.getSelection().getRangeAt(rangeIndex);
    

    rangeIndex 代表Range对象的序号,在chrome或safari中,用户每次只能选取一段区域,因此该值只能为0;

    如何判断用户是否选取了内容?
    可以通过Selection对象的 rangeCount 属性来判断;
    \1. 用户没有按下鼠标该属性值为0;
    \2. 用户按下鼠标之后该属性值为1;
    \3. 用户用鼠标加ctrl键选取了一个或多个区域时,该属性值代表用户通过鼠标选取的区域的数量,当用户取消该区域的选取之后,该属性值为1.
    下面是一个demo;页面上显示一段文字和一个按钮,当用户单击按钮时弹出的提示框中显示用户用鼠标加ctrl键共选取了多少个区域及每一段区域中的内容。代码如下:

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
      <html>
        <head>
          <meta charset="utf-8">
          <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
          <title>标题</title>
        </head>
        <body>
          <h3>Selection对象与Range对象使用demo</h3>
          <input type="button" value="选中我然后点击" onClick="rangeTest()" />
          <div id="showRange"></div>
          <script>
            function rangeTest() {
              var html,
                showRangeDiv=document.getElementById('showRange'),
                selection=document.getSelection();
              if(selection.rangeCount > 0) {
                html = "您选取了"+ selection.rangeCount + "段内容<br/>";
                for(var i = 0; i < selection.rangeCount; i++) {
                  var range = selection.getRangeAt(i);
                  html += "第"+ (i+1) + "段内容为:" + range + "<br/>"; 
                }
                showRangeDiv.innerHTML = html;
              }
            }
          </script>
        </body>
      </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    1-2 Range对象的属性有哪些?
    我们在页面上创建的代码如下:

    var rangeObj = document.createRange();
    console.log(rangeObj);
    

    打印后看到有如下属性:
    collapsed: (Boolean) 用于判断Range对象所代表的区域的开始点和结束点是否位于相同的位置,如果相同该属性值为true。
    commonAncestorContainer: (node) 返回Range对象所代表的区域位于什么节点之中。
    endContainer: (node) 用于返回Range对象所代表的区域的终点位于什么节点之中。
    endOffset(int) 用于返回Range对象所代表区域的终点与包含该终点的节点起点之间的距离。
    startContainer: (node) 用于返回Range对象所代表区域的起点位于什么节点之中。
    startOffset (int) 用于返回Range对象所代表的区域的起点与包含该起点节点的起点之间的距离。

    2 Range对象的方法
    2-1 理解使用 selectNode, selectNodeContents, 与 deleteContents方法
    selectNode: Range对象的selectNode 方法用于将Range对象的起点指定为某个节点的起点,将Range对象的终点指定为该节点的终点。Range对象所代表的区域包含该节点。
    使用方法如下:
    rangeObj.selectNode(node);
    demo举例理解
    假如页面上有一个div,该div包含内容,如果使用 rangeObj.selectNode(“div”); 的含义是,选择该div内的所有内容,包括该div标签本身。

    selectNodeContents: 该方法用于将Range对象的起点指定为某个节点中的所有内容的起点,将Range对象的终点指定为该节点所有内容的终点,也就是说使Range对象所代表的区域包含该节点的所有内容,但是不包括该节点标签本身。

    使用方法如下:
    rangeObj.selectNodeContents(node);
    demo举例理解:
    还是上面的div元素,该元素包含内容,如果使用 rangeObj.selectNodeContents(‘div’);的话,的含义是,选择该div内的所有内容,但是不包括该div本身。

    deleteContents: 该方法用于将Range对象中所包含的内容从页面中删除。
    使用方法如下:
    rangeObj.deleteContents();

    下面是使用一个demo来理解上面的三个方法的具体含义,页面中有一个div元素,一个删除内容的按钮,和一个删除元素的按钮,div元素中显示一些文字,当用户单击 "删除内容"按钮时,会将div元素中的文字从页面中删除,单击 “删除元素” 按钮时,会将整个div元素从页面中删除。

    代码如下:

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
         <html>
            <head>
              <meta charset="utf-8">
              <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
              <title>标题</title>
            </head>
            <body>
              <h3>Selection对象与Range对象使用demo</h3>
              <div id="div" style="background-color: #e0a0b0; width:300px; height: 50px;">aaaaadsadsdasadsbbgg</div>
              <button onclick="deleteRangeContents(true);">删除内容</button>
              <button onclick="deleteRangeContents(false);">删除元素</button>
    
              <script>
                  function deleteRangeContents(flag) {
                    var div = document.getElementById("div");
                    var rangeObj = document.createRange();
                    if (flag) {
                      rangeObj.selectNodeContents(div);
                    } else {
                      rangeObj.selectNode(div);
                    }
                    rangeObj.deleteContents();
                  }
              </script>
            </body>
        </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    2-2 理解使用 setStart方法,setEnd方法,setStartBefore方法,setStartAfter方法,setEndBefore方法与setEndAfter方法

    setStart: 该方法用于将某个节点中的某个位置指定为Range对象所代表区域的起点位置。使用方法如下:
    rangeObj.setStart(node, num);
    num的含义是:首先它是一个整型数值,有两种含义取决于node节点;
    \1. 当第一个参数node所代表的节点是一个内容为一段文字的时候,那么该参数值用于指定将第几个文字结束位置作为Range对象所代表区域的起点位置(num是从0开始)
    \2. 当第一个参数node所代表的节点包括其他子节点时,该参数用于指定将第几个子节点的结束位置作为Range对象所代表区域的起点位置。

    setEnd: 该方法用于将某个节点中的某处位置指定为Range对象所代表区域的结束位置。使用方法如下:
    rangeObj.setEnd(node, num);
    num的含义: 首先是一个整型数值;
    \1. 当第一个参数node所代表的节点是一个内容为一段文字的时候,该参数指定将第几个文字结束位置作为Range对象所代表区域的结束位置。
    \2. 当第一个参数node所代表的节点包括其他子节点时,该参数值用于指定将第几个子节点的结束位置作为Range对象所代表区域的结束位置。

    下面是一个简单的demo来理解上面的 setStart和setEnd方法的使用,页面上有一个div元素和一个删除文字的按钮,div元素中有一些文字,当用户点击 删除文字按钮时,div元素中的第三个文字到第十个文字将被删除。
    代码如下:

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
         <html>
            <head>
              <meta charset="utf-8">
              <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
              <title>标题</title>
            </head>
            <body>
              <div id="myDiv" style="color: red">这段文字中第三个文字到第十个文字将被删除</div>
              <button onclick="deleteChar()">删除文字</button>
              <script>
                function deleteChar() {
                  var div = document.getElementById("myDiv");
                  var textNode = div.firstChild;
                  var rangeObj = document.createRange();
                  rangeObj.setStart(textNode, 2);
                  rangeObj.setEnd(textNode, 10);
                  rangeObj.deleteContents();
                }
              </script>
            </body>
        </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    setStartBefore: 该方法用于将某个节点的起始位置指定为Range对象所代表区域的起点位置。使用方法如下:
    rangeObj.setStartBefore(node);

    setStartAfter: 该方法用于将某个节点的终点位置指定为Range对象所代表区域的起点位置。使用方法如下:
    rangeObj.setStartAfter(node);

    setEndBefore: 该方法用于将某个节点的起始位置指定为Range对象所代表区域的终点位置,使用方法如下:
    rangeObj.setEndBefore(node);

    setEndAfter: 该方法用于将某个节点的终点位置指定为Range对象所代表区域的终点位置。使用方法如下:
    rangeObj.setEndAfter(node);

    看上面的四个方法容易混淆,我们来做一个demo,使用一下 setStartBefore 和 setEndAfter方法。 页面上有一个表格和一个按钮,用户单击按钮时,通过Range对象的setStartBefore 和 setEndAfter方法 使Range对象代表的区域包含表格的第一行,然后删除该行。

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
        <html>
          <head>
            <meta charset="utf-8">
            <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
            <title>标题</title>
          </head>
          <body>
            <table id="myTable" border="1" cellspacing="0" cellpadding="0">
              <tr>
                <td>第一行第一列</td>
                <td>第一行第二列</td>
              </tr>
              <tr>
                <td>第二行第一列</td>
                <td>第二行第二列</td>
              </tr>
            </table>
            <button onclick="deleteFirstRow()">删除第一行</button>
            <script>
              function deleteFirstRow() {
                var myTable = document.getElementById('myTable');
                if (myTable.rows.length > 0) {
                  var row = myTable.rows[0];
                  var rangeObj = document.createRange();
                  rangeObj.setStartBefore(row);
                  rangeObj.setEndAfter(row);
                  rangeObj.deleteContents();
                }
              }
            </script>
          </body>
        </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    2-3 理解使用 cloneRange方法,cloneContents方法,extractContents方法

    cloneRange: 该方法用于对当前的Range对象进行复制,该方法返回复制的Range对象。使用方法如下:
    var rangeClone = rangeObj.cloneRange();
    下面可以看一个demo来理解一下,页面上显示一个 “克隆Range对象” 按钮,用户单击该按钮时,创建一个Range对象,该对象包含页面中的所有内容,然后使用cloneRange方法复制Range对象,然后在弹窗显示该Range对象中的内容。
    代码如下:

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
       <html>
          <head>
            <meta charset="utf-8">
            <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
            <title>标题</title>
          </head>
          <body>
            <button onclick="cloneRange()">克隆Range对象</button>
            <script>
              function cloneRange() {
                var rangeObj = document.createRange();
                rangeObj.selectNodeContents(document.body);
                var rangeClone = rangeObj.cloneRange();
                console.log(rangeClone);
                alert(rangeClone.toString());
              }
            </script>
          </body>
      </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    cloneContents: 该方法用于在页面上追加一段HTML代码,使用方法如下:
    var docFragment = rangeObj.cloneContents();
    该方法返回的是 一个 DocumentFragment对象,该对象为一个容器元素,当需要追加,修改,删除或查找页面上的元素时,该方法非常有用。
    下面是一个demo,页面上显示一个div元素,div元素中包含一些文字和一个按钮,用户点击按钮时将在该div元素底部克隆出相同的文字和按钮。

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
       <html>
          <head>
            <meta charset="utf-8">
            <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
            <title>标题</title>
          </head>
          <body>
            <div id="div">
              <span>aaaaaa</span>
              <button onclick="cloneDivContent()">克隆</button>
            </div>
            <script>
              function cloneDivContent() {
                var div = document.getElementById('div');
                var rangeObj = document.createRange();
                rangeObj.selectNodeContents(div);
                var documentFragment = rangeObj.cloneContents();
                div.appendChild(documentFragment);
              }
            </script>
          </body>
      </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    extraContents: 该方法用于将Range对象所代表区域的HTML代码克隆到一个 DocumentFragment中,然后从页面中删除这段HTML代码;

    使用方法如下:
    var documentFragment = rangeObj.extraContents();

    下面是一个demo, 页面上有2个div元素和一个按钮,其中第一个div元素包含一些文字,用户单击该按钮时,把文字移动到第二个div中。

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
       <html>
          <head>
            <meta charset="utf-8">
            <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
            <title>标题</title>
          </head>
          <body>
            <div id="srcDiv" style="background-color: red; width: 300px; height:50px">adsddasdssdsdsdsads</div>
            <div id="distDiv" style="background-color: blue; width: 300px; height: 50px;"></div>
            <button onclick="moveContent()">移动元素内容</button>
    
            <script>
              function moveContent() {
                var srcDiv = document.getElementById('srcDiv');
                var distDiv = document.getElementById("distDiv");
                var rangeObj = document.createRange();
                rangeObj.selectNodeContents(srcDiv);
                var documentFragment = rangeObj.extractContents();
                distDiv.appendChild(documentFragment);
              }
            </script>
          </body>
      </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    2-4 insertNode方法
    该方法用于将指定的节点插入到某个Range对象所代表的区域中,插入位置为Range对象所代表区域的起点位置,如果该节点已经存在于页面之中,那么该节点
    将被移动到Range对象所代表区域的起点处。
    使用方法如下:
    rangeObj.insertNode(node)

    下面是一个demo,页面中有一个div元素和一个按钮,div元素有一些文字,在div元素中按下鼠标左键时,该按钮将被移动到按下鼠标左键的位置。

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
       <html>
          <head>
            <meta charset="utf-8">
            <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
            <title>标题</title>
          </head>
          <body>
            <div onmouseup="moveButton()" style="width: 400px; background-color: red;">adssdasddsdasszczxccxzcx</div>
            <button id="button">按钮</button>
    
            <script>
              function moveButton() {
                var button = document.getElementById("button");
                var selection = document.getSelection();
                if (selection.rangeCount > 0) {
                  var range = selection.getRangeAt(0);
                  range.insertNode(button);
                }
              }
            </script>
          </body>
      </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    2-5 理解collapse方法 和 detach方法
    该方法用于将Range对象所代表的区域的终点移动到该区域的起点处,或将Range对象所代表的区域的起点移动到终点处,使Range对象所代表的区域内不包含任何内容。
    使用方法如下:
    RangeObj.collapse(toStart);
    参数toStart,是一个Boolean型,如果为false的话,表示将Range对象所代表的区域的起点移动到终点处,当为true的话,表示将Range对象所代表的区域的终点移动到该区域的起点处。
    下面是一个demo,可以来理解下 collapse方法的使用;
    页面上有一个div元素,里面包含一些文字,一个 选择元素的 按钮,一个 取消选择元素的按钮,和一个 显示Range内容的按钮,用户单击 选择元素 按钮时该Range对象中将包含页面中的div元素,然后单击 显示Range内容按钮 就弹出 该div元素的内容,再单击 取消选择按钮 将使用Range对象的collapse方法清空Range对象的内容。再次单击 显示Range内容,将显示空字符串。
    代码如下:

    [复制代码](javascript:void(0)?

    <!DOCTYPE html>
           <html>
              <head>
                <meta charset="utf-8">
                <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
                <title>标题</title>
              </head>
              <body>
                <div id="div" style="background-color: red; width:300px; height: 50px;">元素中的内容</div>
                <button onclick="selectRangeContents()">选择元素</button>
                <button onclick="unselect()">取消选择</button>
                <button onclick="showRange()">显示Range内容</button>
                <script>
                  var rangeObj = document.createRange();
                  function selectRangeContents() {
                    var div = document.getElementById('div');
                    rangeObj.selectNode(div);
                  }
                  function unselect() {
                    rangeObj.collapse(false);
                  } 
                  function showRange() {
                    alert(rangeObj.toString());
                  }
                </script>
              </body>
          </html>
    

    [复制代码](javascript:void(0)?

    查看效果

    detach方法: 该方法用于从浏览器中释放Range对象,释放之后将不能再访问该Range对象,否则将抛出脚本错误,使用方法如下:
    RangeObj.detach();

    展开全文
  • Full Range&Limited Range

    千次阅读 2019-11-24 22:47:40
     AV领域的视频设备是从16~235之间取值的,不过实际上很多中高端的DVD播放器、电视机和投影机都可以选择PC Leve(l Full Range)或者Studio Level(Limited Range)模式来适应不同的状况。  如果HTPC输出的信号是0...
  • C#:泛型Range助手

    千次阅读 2019-07-01 21:47:31
    目录 介绍 背景 我们会做什么? 范围(Range)模型 ...默认情况下,在C#中,我们有Enumerable.Range(Int32, Int32) ,其生成一个指定范围内的整数序列。我们期待着一种管理不同数据类型范围而不仅仅是整...
  • np.arange()和 range()的用法及区别

    千次阅读 2021-07-16 20:19:02
    np.arange() np.arange()函数返回一个有终点和起点的固定步长的排列,如[1,2,3,4,5],起点是1,终点是6,步长为1。 参数个数情况: np.arange()函数分为一个参数,两个参数,三个参数三种情况 一个参数时,参数值...
  • np.arange() 详细教程

    千次阅读 2020-11-27 08:37:24
    NumPyis the fundamental Python library for numerical computing.... NumPy offers a lot ofarray creation routinesfor different circumstances.arange()is one such function based onnumerical ranges. It...
  • 浅谈Python中range与Numpy中arange的比较

    千次阅读 2021-01-29 04:25:23
    本文先比较range与arange的异同点,再详细介绍各自的用法,然后列举了几个简单的示例,最后对xrange进行了简单的说明。1. range与arange的比较(1)相同点:A、参数的可选性、默认缺省值是一样的;B、结果均包括开始值...
  • python range函数语法以及一些讨论

    千次阅读 2020-12-29 11:10:18
    迭代器是 23 种设计模式中最常用的一种(之一),在 Python 中随处可见它的身影,我们经常用到它,但是却不一定意识...在系统学习迭代器之前,我一直以为 range() 方法也是用于生成迭代器的,现在却突然发现,它生成的...
  • 【问题发现】 相信很多使用Python的小伙伴,都用到过range()函数,进行循环或遍历。 for i in range(len(a)): print(a[i]) 但当我们用得正嗨时,可能突然看到其他作者的代码中用的并不是range()函数,而是arange()...
  • 使用python的人都知道range()函数很方便,今天再用到他的时候发现了很多以前看到过但是忘记的细节。这里记录一下range(),复习下list的slide,最后分析一个好玩儿的冒泡程序。这里记录一下:>>> range(1,5) ...
  • Python浮点数range

    千次阅读 2021-01-28 18:20:24
    问题提出:最近在用matplotlib定义坐标轴,需要会出现型如...最初觉得这个问题很简单, 虽然python的range是不支持浮点数的,np可以实现出现下面的代码```import numpy as np print(list(map(lambda a:str(a),np.ara...
  • Java range工具类(自定义)

    千次阅读 2020-09-02 09:37:32
    在python中存在range函数,效果如下: 即可指定range的step,而在Java中IntStream只能指定start, end,而正好项目中需要使用该特性,且需要对列表进行拆分,故实现了如下工具类。 工具代码 import ...
  • Full Range && Limit Range

    千次阅读 2020-12-01 22:04:16
    Limit Range1 Full range和Limit Range定义2 为什么会需要Limit Range3 用Full range去显示limit Range图片4 YUV转RGB5 额外 1 Full range和Limit Range定义 我们知道,对于RGB和YUV的色彩空间来说,有个位深(bit-...
  • Python中的arange是什么意思?这是很多小伙伴都比较关注的问题,今天小编为大家详细介绍一下,希望对你...比如for循环中,几乎都会用到range,至于arangerange的区别,仅仅只是arange返回的是一个数据,而range返回...
  • python range用法

    千次阅读 2020-12-19 18:06:54
    Python range() 函数用法python range() 函数可创建一个整数列表,一般用在 for 循环中。函数语法range(start, stop[, step])参数说明:start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5)...
  • Python – numpy.arange()

    千次阅读 2020-07-06 18:34:52
    Being a linear sequence generator, the numpy.arange() function is used to generate a sequence of numbers in linear space with a uniform step size. 作为线性序列生成器, numpy.arange()函数用于在线性空间...
  • 自定义支持 float 的 range 函数

    千次阅读 2020-12-09 06:34:34
    python range() 函数是步进函数,可快速优雅地创建一个整数列表,一般用在 for 循环中。但是 python 自带的 range() 步进函数只支持整数类型,不支持浮点数。那么,为了支持浮点数,我们只能自定义一个函数。1、...
  • range在python中的意思是什么

    千次阅读 2020-12-18 03:40:05
    range在python中的意思是什么发布时间:2020-07-20 11:56:31来源:亿速云阅读:109这期内容当中小编将会给大家带来有关range在python中的意思是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章...
  • Python中range()函数的使用方法

    万次阅读 多人点赞 2022-02-17 16:10:55
    range()函数可以产生一系列的数字。当需要叠加一些数字时,可以用到range()函数。 1 基本语法 range()函数的基本语法如下所示。 range(start, stop) 其中,start表示这一些列数字中的第一个数字;stop-1表示这...
  • ES系列:range范围查询使用举例

    千次阅读 2022-02-17 20:55:34
    range过滤允许我们按照指定范围查找一批数据 { "range": { "age": { "gte": 20, "lt": 30 } } } ​ gt :: 大于 gte:: 大于等于 lt :: 小于 lte:: 小于等于 时间范围 完整日期方式 ...
  • 为什么Python里面的range不包含上界?

    千次阅读 2021-03-17 16:46:36
    例如 range(1,5),其实只包含1,2,3,4 即便是range(0,6,2),也不包含6。如果数不在range里那在range里出现这个数字的含义何在? 数组从0开始记数我已经忍了,range不含上界这是一个什么意思?这还让slice等等操作...
  • range() 函数 1. 何为 range() 首先我们需要知道 range() 函数返回的到底是一个什么东西: from collections import Iterable from collections import Iterator x = range(100) print(isinstance(x, Iterable)) ...
  • Excel VBA Range单元格操作实例

    千次阅读 2020-02-16 21:51:53
    四、Range操作 4.2取得最后一个非空单元格 xlDown/xlToRight/xlToLeft/xlUp Dim ERow as Long Erow=Range("A" & Rows.Count).End(xlUp).Row 4.3 复制单元格区域 注意:使用PasteSpecial方法时指定xlPasteAll...
  • 在压缩算法中,熵编码是其中重要的无损压缩步骤。...目前各类压缩工具使用的熵编码算法主要有Huffman coding,Arithmetic coding, Range coding和新出的Asymmetric Number System这几种算法。其中Huffman...
  • 为什么range不是迭代器?range到底是什么类型?

    千次阅读 多人点赞 2019-01-05 07:50:42
    迭代器是 23 种设计模式中最常用的一种(之一),在 Python 中随处可见它的身影,我们经常用到它,但是却不一定意识...在系统学习迭代器之前,我一直以为 range() 方法也是用于生成迭代器的,现在却突然发现,它生成...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,255,320
精华内容 902,128
关键字:

range()