精华内容
下载资源
问答
  • Kotlin系列之let、with、run、apply、also函数的使用

    万次阅读 多人点赞 2017-12-12 21:59:53
    三、内联函数之with 四、内联扩展函数之run 五、内联扩展函数之apply 六、内联扩展函数之also 七、let,with,run,apply,also函数区别 简述: 相比Java, Kotlin提供了不少高级语法特性。对于一个Kotlin的初学者来说

    标签: Kotlin      常用技巧


    目录:

    简述:

    相比Java, Kotlin提供了不少高级语法特性。对于一个Kotlin的初学者来说经常会写出一些不够优雅的代码。在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码。Standard.kt是Kotlin库的一部分,它定义了一些基本函数。 这个源代码文件虽然一共不到50行代码,但是这些函数功能都非常强大。


    一、回调函数的Kotin的lambda的简化

    在Kotlin中对Java中的一些的接口的回调做了一些优化,可以使用一个lambda函数来代替。可以简化写一些不必要的嵌套回调方法。但是需要注意:在lambda表达式,只支持单抽象方法模型,也就是说设计的接口里面只有一个抽象的方法,才符合lambda表达式的规则,多个回调方法不支持。

    • 1、用Java代码实现一个接口的回调。

       mView.setEventListener(new ExamPlanHomeEventListener(){
       
          public void onSuccess(Data data){
            //todo
          }
       
       });
      
      
    • 2、在Kotlin中的实现一个接口的回调,不使用lambda表达式(这种方式非常适用于kotlin中对于一个接口中含有多个回调方法)。

      
      mView.setEventListener(object: ExamPlanHomeEventListener{
           
          public void onSuccess(Data data){
            //todo
          }
           
      });
      
    • 3、如果在Kotlin中的对于接口只有一个回调的方法,就符合使用lambda函数,我们可以把以上代码简化成这样。

      mView.setEventListener({
         data: Data ->
         //todo
      })
      
      //或者可以直接省略Data,借助kotlin的智能类型推导
      
      mView.setEventListener({
         data ->
         //todo
      })
      
    • 4、如果以上代码中的data参数没有使用到的话,可以直接把data去掉

      mView.setEventListener({
        //todo
      
      })
      
    • 5、以上代码还可以做个调整,由于setEventListener函数最后一个参数是一个函数的话,可以直接把括号的实现提到圆括号外面

      mView.setEventListener(){
         //todo
      }
      
    • 6、由于setEventListener这个函数只有一个参数,可以直接省略圆括号

      mView.setEventListener{
        //todo
      }
      

    二、内联扩展函数之let

    let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。
    
    • 1、let函数的使用的一般结构
    object.let{
       it.todo()//在函数体内使用it替代object对象去访问其公有的属性和方法
       ...
    }
    
    //另一种用途 判断object为null的操作
    object?.let{//表示object不为null的条件下,才会去执行let函数体
       it.todo()
    }
    
    • 2、let函数底层的inline扩展函数+lambda结构
       @kotlin.internal.InlineOnly
    public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
    
    • 3、let函数inline结构的分析

      从源码let函数的结构来看它是只有一个lambda函数块block作为参数的函数,调用T类型对象的let函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为函数块的最后一行或指定return表达式。

    • 4、let函数的kotlin和Java转化

       //kotlin
       
       fun main(args: Array<String>) {
          val result = "testLet".let {
              println(it.length)
              1000
          }
          println(result)
       }
       
       //java
       
       public final class LetFunctionKt {
         public static final void main(@NotNull String[] args) {
            Intrinsics.checkParameterIsNotNull(args, "args");
            String var2 = "testLet";
            int var4 = var2.length();
            System.out.println(var4);
            int result = 1000;
            System.out.println(result);
         }
      }
      
       
      
    • 5、let函数适用的场景

      场景一: 最常用的场景就是使用let函数处理需要针对一个可null的对象统一做判空处理。

      场景二: 然后就是需要去明确一个变量所处特定的作用域范围内可以使用

    • 6、let函数使用前后的对比

      没有使用let函数的代码是这样的,看起来不够优雅

      mVideoPlayer?.setVideoView(activity.course_video_view)
      	mVideoPlayer?.setControllerView(activity.course_video_controller_view)
      	mVideoPlayer?.setCurtainView(activity.course_video_curtain_view)
      

    使用let函数后的代码是这样的

    ```
    mVideoPlayer?.let {
    	   it.setVideoView(activity.course_video_view)
    	   it.setControllerView(activity.course_video_controller_view)
    	   it.setCurtainView(activity.course_video_curtain_view)
    }
    	
    ```
    

    三、内联函数之with

    • 1、with函数使用的一般结构

       with(object){
         //todo
       }
      
    • 2、with函数底层的inline扩展函数+lambda结构

      @kotlin.internal.InlineOnly
      public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
      
      
    • 3、with函数inline结构的分析

    with函数和前面的几个函数使用方式略有不同,因为它不是以扩展的形式存在的。它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。

    可以看出with函数是接收了两个参数,分别为T类型的对象receiver和一个lambda函数块,所以with函数最原始样子如下:

    ```
    
    val result = with(user, {
            println("my name is $name, I am $age years old, my phone number is $phoneNum")
            1000
        })
    ```
    

    但是由于with函数最后一个参数是一个函数,可以把函数提到圆括号的外部,所以最终with函数的调用形式如下:

    ```
    val result = with(user) {
            println("my name is $name, I am $age years old, my phone number is $phoneNum")
            1000
        }
    ```
    
    • 4、with函数的kotlin和Java转化

      //kotlin
      
      fun main(args: Array<String>) {
          val user = User("Kotlin", 1, "1111111")
      
          val result = with(user) {
              println("my name is $name, I am $age years old, my phone number is $phoneNum")
              1000
          }
          println("result: $result")
      }
      
      //java
      
       public static final void main(@NotNull String[] args) {
            Intrinsics.checkParameterIsNotNull(args, "args");
            User user = new User("Kotlin", 1, "1111111");
            String var4 = "my name is " + user.getName() + ", I am " + user.getAge() + " years old, my phone number is " + user.getPhoneNum();
            System.out.println(var4);
            int result = 1000;
            String var3 = "result: " + result;
            System.out.println(var3);
         }
      
      
    • 5、with函数的适用的场景

    适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上

    • 6、with函数使用前后的对比

    没有使用kotlin中的实现

    ```
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    
       ArticleSnippet item = getItem(position);
    		if (item == null) {
    			return;
    		}
    		holder.tvNewsTitle.setText(StringUtils.trimToEmpty(item.titleEn));
    		holder.tvNewsSummary.setText(StringUtils.trimToEmpty(item.summary));
    		String gradeInfo = "难度:" + item.gradeInfo;
    		String wordCount = "单词数:" + item.length;
    		String reviewNum = "读后感:" + item.numReviews;
    		String extraInfo = gradeInfo + " | " + wordCount + " | " + reviewNum;
    		holder.tvExtraInfo.setText(extraInfo);
    		...
    }
    
    ```
    

    kotlin的实现

    ```
    override fun onBindViewHolder(holder: ViewHolder, position: Int){
       val item = getItem(position)?: return
       
       with(item){
       
          holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
    	   holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
    	   holder.tvExtraInf.text = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
           ...   
       
       }
    
    }
    
    ```
    

    四、内联扩展函数之run

    • 1、run函数使用的一般结构

      object.run{
      //todo
      }
      
    • 2、run函数的inline+lambda结构

      @kotlin.internal.InlineOnly
      public inline fun <T, R> T.run(block: T.() -> R): R = block()
      
    • 3、run函数的inline结构分析

      run函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式。

    • 4、run函数的kotlin和Java转化

      //kotlin
      
      fun main(args: Array<String>) {
          val user = User("Kotlin", 1, "1111111")
      
          val result = user.run {
              println("my name is $name, I am $age years old, my phone number is $phoneNum")
              1000
          }
          println("result: $result")
      }
      
      //java
      
        public static final void main(@NotNull String[] args) {
            Intrinsics.checkParameterIsNotNull(args, "args");
            User user = new User("Kotlin", 1, "1111111");
            String var5 = "my name is " + user.getName() + ", I am " + user.getAge() + " years old, my phone number is " + user.getPhoneNum();
            System.out.println(var5);
            int result = 1000;
            String var3 = "result: " + result;
            System.out.println(var3);
         }
      
      
    • 5、run函数的适用场景

    适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理

    • 6、run函数使用前后的对比

    还是借助上个例子kotlin代码

    ```
    override fun onBindViewHolder(holder: ViewHolder, position: Int){
       val item = getItem(position)?: return
       
       with(item){
       
          holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
    	   holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
    	   holder.tvExtraInf = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
           ...   
       
       }
    
    }
    ```
    

    使用run函数后的优化

    ```
    override fun onBindViewHolder(holder: ViewHolder, position: Int){
       
      getItem(position)?.run{
          holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
    	   holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
    	   holder.tvExtraInf = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
           ...   
       
       }
    
    }
    
    ```
    

    五、内联扩展函数之apply

    • 1、apply函数使用的一般结构

      object.apply{
      //todo
      }
      
    • 2、apply函数的inline+lambda结构

      @kotlin.internal.InlineOnly
      public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
      
    • 3、apply函数的inline结构分析

    从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身。

    • 4、apply函数的kotlin和Java转化

      //kotlin
      
      fun main(args: Array<String>) {
          val user = User("Kotlin", 1, "1111111")
      
          val result = user.apply {
              println("my name is $name, I am $age years old, my phone number is $phoneNum")
              1000
          }
          println("result: $result")
      }
      
      //java
      
      public final class ApplyFunctionKt {
         public static final void main(@NotNull String[] args) {
            Intrinsics.checkParameterIsNotNull(args, "args");
            User user = new User("Kotlin", 1, "1111111");
            String var5 = "my name is " + user.getName() + ", I am " + user.getAge() + " years old, my phone number is " + user.getPhoneNum();
            System.out.println(var5);
            String var3 = "result: " + user;
            System.out.println(var3);
         }
      }
      
      
    • 5、apply函数的适用场景

    整体作用功能和run函数很像,唯一不同点就是它返回的值是对象本身,而run函数是一个闭包形式返回,返回的是最后一行的值。正是基于这一点差异它的适用场景稍微与run函数有点不一样。apply一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值。或者动态inflate出一个XML的View的时候需要给View绑定数据也会用到,这种情景非常常见。特别是在我们开发中会有一些数据model向View model转化实例化的过程中需要用到。

    • 6、apply函数使用前后的对比

    没有使用apply函数的代码是这样的,看起来不够优雅

    ```
    mSheetDialogView = View.inflate(activity, R.layout.biz_exam_plan_layout_sheet_inner, null)
            mSheetDialogView.course_comment_tv_label.paint.isFakeBoldText = true
            mSheetDialogView.course_comment_tv_score.paint.isFakeBoldText = true
            mSheetDialogView.course_comment_tv_cancel.paint.isFakeBoldText = true
            mSheetDialogView.course_comment_tv_confirm.paint.isFakeBoldText = true
            mSheetDialogView.course_comment_seek_bar.max = 10
            mSheetDialogView.course_comment_seek_bar.progress = 0
    ```
    

    使用apply函数后的代码是这样的

    ```
    mSheetDialogView = View.inflate(activity, R.layout.biz_exam_plan_layout_sheet_inner, null).apply{
       course_comment_tv_label.paint.isFakeBoldText = true
       course_comment_tv_score.paint.isFakeBoldText = true
       course_comment_tv_cancel.paint.isFakeBoldText = true
       course_comment_tv_confirm.paint.isFakeBoldText = true
       course_comment_seek_bar.max = 10
       course_comment_seek_bar.progress = 0
    
    }
    
    ```
    

    多层级判空问题

    ```
    	if (mSectionMetaData == null || mSectionMetaData.questionnaire == null || mSectionMetaData.section == null) {
    			return;
    		}
    		if (mSectionMetaData.questionnaire.userProject != null) {
    			renderAnalysis();
    			return;
    		}
    		if (mSectionMetaData.section != null && !mSectionMetaData.section.sectionArticles.isEmpty()) {
    			fetchQuestionData();
    			return;
    		}
    ```
    

    kotlin的apply函数优化

    ```
    mSectionMetaData?.apply{
    
    //mSectionMetaData不为空的时候操作mSectionMetaData
    
    }?.questionnaire?.apply{
    
    //questionnaire不为空的时候操作questionnaire
    
    }?.section?.apply{
    
    //section不为空的时候操作section
    
    }?.sectionArticle?.apply{
    
    //sectionArticle不为空的时候操作sectionArticle
    
    }
    
    ```
    

    六、内联扩展函数之also

    • 1、also函数使用的一般结构

      object.also{
      //todo
      }
      
    • 2、also函数的inline+lambda结构

      @kotlin.internal.InlineOnly
      

    @SinceKotlin(“1.1”)
    public inline fun T.also(block: (T) -> Unit): T { block(this); return this }
    ```

    • 3、also函数的inline结构分析

    also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身

    • 4、also函数编译后的class文件

      //kotlin
      
      fun main(args: Array<String>) {
          val result = "testLet".also {
              println(it.length)
              1000
          }
          println(result)
      }
      
      //java
      
      public final class AlsoFunctionKt {
         public static final void main(@NotNull String[] args) {
            Intrinsics.checkParameterIsNotNull(args, "args");
            String var2 = "testLet";
            int var4 = var2.length();
            System.out.println(var4);
            System.out.println(var2);
         }
      }
      
    • 5、also函数的适用场景

      适用于let函数的任何场景,also函数和let很像,只是唯一的不同点就是let函数最后的返回值是最后一行的返回值而also函数的返回值是返回当前的这个对象。一般可用于多个扩展函数链式调用

    • 6、also函数使用前后的对比

      和let函数类似

    七、let,with,run,apply,also函数区别

    通过以上几种函数的介绍,可以很方便优化kotlin中代码编写,整体看起来几个函数的作用很相似,但是各自又存在着不同。使用的场景有相同的地方比如run函数就是let和with的结合体。下面一张表格可以清晰对比出他们的不同之处。

    函数名定义inline的结构函数体内使用的对象返回值是否是扩展函数适用的场景
    letfun <T, R> T.let(block: (T) -> R): R = block(this)it指代当前对象闭包形式返回适用于处理不为null的操作场景
    withfun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()this指代当前对象或者省略闭包形式返回适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上
    runfun <T, R> T.run(block: T.() -> R): R = block()this指代当前对象或者省略闭包形式返回适用于let,with函数任何场景。
    applyfun T.apply(block: T.() -> Unit): T { block(); return this }this指代当前对象或者省略返回this1、适用于run函数的任何场景,一般用于初始化一个对象实例的时候,操作对象属性,并最终返回这个对象。
    2、动态inflate出一个XML的View的时候需要给View绑定数据也会用到.
    3、一般可用于多个扩展函数链式调用
    4、数据model多层级包裹判空处理的问题
    alsofun T.also(block: (T) -> Unit): T { block(this); return this }it指代当前对象返回this适用于let函数的任何场景,一般可用于多个扩展函数链式调用

    欢迎关注Kotlin开发者联盟,这里有最新Kotlin技术文章,每周会不定期翻译一篇Kotlin国外技术文章。如果你也喜欢Kotlin,欢迎加入我们~~~

    Kotlin系列文章,欢迎查看:

    Kotlin邂逅设计模式系列:

    数据结构与算法系列:

    翻译系列:

    原创系列:

    Effective Kotlin翻译系列

    实战系列:

    展开全文
  • python的with用法

    万次阅读 多人点赞 2016-10-06 21:18:11
    1.With语句是什么?有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭...

    项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
    欢迎大家star,留言,一起学习进步

    1.With语句是什么?

    有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

    如果不用with语句,代码如下:

    file = open("/tmp/foo.txt")
    data = file.read()
    file.close()
    

    这里有两个问题:

    一是可能忘记关闭文件句柄;
    二是文件读取数据发生异常,没有进行任何处理。

    下面是处理异常的加强版本:

    try:
        f = open('xxx')
    except:
        print 'fail to open'
        exit(-1)
    try:
        do something
    except:
        do something
    finally:
         f.close()
    

    虽然这段代码运行良好,但是太冗长了。

    这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。

    下面是with版本的代码:

    with open("/tmp/foo.txt") as file:
        data = file.read()
    

    2.with如何工作?

    紧跟with后面的语句被求值后,返回对象的 _enter_() 方法被调用,这个方法的返回值将被赋值给as后面的变量。
    当with后面的代码块全部被执行完之后,将调用前面返回对象的 _exit_()方法。

    下面例子可以具体说明with如何工作:

    #!/usr/bin/env python
    # with_example01.py
    class Sample:
        def __enter__(self):
            print "In __enter__()"
            return "Foo"
        def __exit__(self, type, value, trace):
            print "In __exit__()"
    def get_sample():
        return Sample()
    with get_sample() as sample:
        print "sample:", sample
    

    运行代码,输出如下

    bash-3.2$ ./with_example01.py
    In __enter__()
    sample: Foo
    In __exit__()
    

    正如你看到的: 1. _enter_()方法被执行 2. _enter_()方法返回的值 - 这个例子中是”Foo”,赋值给变量’sample’ 3. 执行代码块,打印变量”sample”的值为 “Foo” 4. _exit_()方法被调用
    with真正强大之处是它可以处理异常。可能你已经注意到Sample类的 _exit_ 方法有三个参数 val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。

    #!/usr/bin/env python
    # with_example02.py
    class Sample:
        def __enter__(self):
            return self
        def __exit__(self, type, value, trace):
            print "type:", type
            print "value:", value
            print "trace:", trace
        def do_something(self):
            bar = 1/0
            return bar + 10
    with Sample() as sample:
        sample.do_something()
    

    这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有 _enter_() 和 _exit_() 方法即可。此例中,Sample()的 _enter_() 方法返回新创建的Sample对象,并赋值给变量sample。

    代码执行后:

    bash-3.2$ ./with_example02.py
    type: <type 'exceptions.ZeroDivisionError'>
    value: integer division or modulo by zero
    trace: <traceback object at 0x1004a8128>
    Traceback (most recent call last):
      File "./with_example02.py", line 19, in <module>
        sample.do_something()
      File "./with_example02.py", line 15, in do_something
        bar = 1/0
    ZeroDivisionError: integer division or modulo by zero
    

    实际上,在with后面的代码块抛出任何异常时,_exit_() 方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给 _exit_() 方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在 _exit_ 方法当中。

    另外,_exit_ 除了用于tear things down,还可以进行异常的监控和处理,注意后几个参数。要跳过一个异常,只需要返回该函数True即可。

    下面的样例代码跳过了所有的TypeError,而让其他异常正常抛出。

    def __exit__(self, type, value, traceback):
        return isinstance(value, TypeError)
    

    上文说了 _exit_ 函数可以进行部分异常的处理,如果我们不在这个函数中处理异常,他会正常抛出,这时候我们可以这样写(python 2.7及以上版本,之前的版本参考使用contextlib.nested这个库函数):

    try:
        with open( "a.txt" ) as f :
            do something
    except xxxError:
        do something about exception
    

    总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码的优雅性是有极大帮助的。

    如果有多个项,我们可以这么写:

    with open("x.txt") as f1, open('xxx.txt') as f2:
        do something with f1,f2
    

    因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。

    3.相关术语

    要使用 with 语句,首先要明白上下文管理器这一概念。有了上下文管理器,with 语句才能工作。
    下面是一组与上下文管理器和with 语句有关的概念。
    上下文管理协议(Context Management Protocol):包含方法 _enter_() 和 _exit_(),支持该协议的对象要实现这两个方法。
    上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了_enter_() 和 _exit_() 方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。
    运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的 _enter_() 和_exit_() 方法实现,_enter_() 方法在语句体执行之前进入运行时上下文,_exit_() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。
    上下文表达式(Context Expression):with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。
    语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 _enter_() 方法,执行完语句体之后会执行_exit_() 方法。

    相关链接:
    1.http://blog.kissdata.com/2014/05/23/python-with.html
    2.https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

    展开全文
  • Python3中打开文件的方式(With open)

    万次阅读 多人点赞 2018-08-05 19:53:16
    所以,Python引入了with语句来自动帮我们调用close()方法: with 的作用就是调用close()方法 with open( '/path/to/file', 'r' ) as f: print( f.read() ) f.read() 读取全部文件内容 这和前面的try ......

    0.背景知识 & IO操作的类型

    • python文件读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。
    • 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘。
    • 读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)

    常见的IO操作的类型如下:

    typeinfo
    r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
    w打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
    wb以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    r+打开一个文件用于读写。文件指针将会放在文件的开头。
    w+打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
    rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
    wb+以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。


    1.常规方式:读取文件-----open()


    step1: 打开

    
    f = open( '/Users/michael/test.txt', 'r' )
    
    
    • r 表示读取文件,我们就成功地打开了一个文件
    • 但是, 如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在,错误情况如下:
    
    f=open('/Users/michael/notfound.txt', 'r')
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/notfound.txt'
    
    

    step2: 读取

    如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示:

    
    f.read()
    'Hello, world!'
    
    

    step3: 关闭

    最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的:

    
    f.close()
    
    

    由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try … finally来实现:

    最终方案:

    
    try:
    	f = open('/path/to/file', 'r')
    	print(f.read())
    finally:
    	if f:
    		f.close()
    		
    


    2.推荐方式:读取文件-----With Open

    1).读取方式

    每次如果都按照如上最终方案去写的话,实在太繁琐。Python引入了with语句来自动帮我们调用close()方法
    重点:!!!with 的作用就是自动调用close()方法 !!!

    
    with open( '/path/to/file', 'r' ) as f:
    	print( f.read() ) 
    
    # 这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法
    	
    

    f.read(): 读取全部文件内容
    f.read(size): 每次读取size个字节内容
    f.readline(): 每次读取一行的内容
    f.readlines(): 读取全部内容,但结果是个list,每行内容是一个元素


    如果遇到超大文件,需要注意:

    • 调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了。
    • 要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。例如,read(1024) 每次读取1024个字节的数据内容
    • 调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。
    • 如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便:
    
    for line in f.readlines():
    	print( line.strip() ) 
    
    
    # 读取文件之后,文字末尾会出现'\n'
    # strip() 函数中可以把目标内容line里面所有的空格,空行等都删除掉,只剩余文字内容
    


    2).常见的坑

    这里写图片描述

    读取静态文件的函数,最好不要写相对路径!!!

    (1)如上图,Fold001文件夹下面有个read_file.py文件,这个文件读取hello.txt文件,代码如上图,这样可以正常引用
    (2)但如果引用静态文件的函数,被其他函数再次调用的时候。 例如被Fold002里面的函数read.py调用,那么readfile()函数相当于是在read.py所在目录执行的,那么静态文件hello.txt相对于read.py的路径,就不是上图的路径了,否者会运行会报错,如下

    这里写图片描述



    3.写入内容----open()函数

    写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件:

    
    f = open('/Users/michael/test.txt', 'w')
    f.write('Hello, world!')
    f.close()
    
    

    open函数使用注意地方:

    • 你可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。
    • 当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
    • 只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险


    4.写入内容----- With Open函数

    
    with open('/Users/michael/test.txt', 'w') as f:
    	f.write('Hello, world!')
    	
    

    要写入特定编码的文本文件,请给open()函数传入encoding参数,将字符串自动转换成指定编码字符编码



    5.打开非utf-8编码的文件

    要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

    
    with open('/Users/michael/gbk.txt', 'r', encoding='gbk') as f:
        f.read()
    	
    
    • 遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。
    • open()函数还接收一个errors参数,errors=‘ignore’ 表示遇到编码错误的时候直接忽略
    
    with open('/Users/michael/gbk.txt', 'r', encoding='gbk',errors='ignore') as f:
        f.read()
        
    


    6.打开二进制文件

    前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用’rb’模式打开文件即可:

    
    with open('/Users/michael/test.jpg', 'rb') as f:
        f.read()
    
    #  b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...'            十六进制表示的字节
    
    
    展开全文
  • 什么有的句子中with前直接接在所修饰词后,有的with前却加了逗号??? 例程:He gave his card,with a few words in pencil. He gave his card,with a few words in pencil. 翻译:他把它的名便给我,上面有几个...

    为什么有的句子中with前直接接在所修饰词后,有的with前却加了逗号???
    例程:He gave his card,with a few words in pencil. He gave his card,with a few words in pencil.
    翻译:他把它的名便给我,上面有几个铅笔字
    解析:with a few words in pecil是伴随状态,所以要用逗号,前面是一个完整的句子。而有时候He write with a pen.像这个句子前半句并非是一个完整的句子,所以不能用逗号
    例程:Flask has many configuration values, with sensible defaults, and a few conventions when getting started.
    展开全文
  • Python with语句定义及使用

    万次阅读 2018-09-10 09:07:10
    如果你有一些对象(比如一个文件、网络连接或锁),需要支持 with 语句,下面介绍两种定义方法。...(2)当with后面的代码块全部被执行完之后,将调用前面返回对象的“__exit__()”方法。 with工作原理...
  • Python 中 with用法及原理

    万次阅读 多人点赞 2017-06-08 11:22:17
    前言with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭/线程中锁的自动获取和释放等。
  • Oracle WITH AS 用法

    千次阅读 2018-01-11 18:15:55
    可以把WITH AS 的用法看成赋值的用法,以减少SQL语句的冗余。 当我们在SQL语句中频繁的利用某一个Select查询语句作为数据源时,我们可以用WITH AS 的用法进行简写 增加了SQL的易读性,如果构造了多个子查询,结构...
  • HTTP之X-Requested-With分析和思考

    万次阅读 2016-01-22 17:05:06
    本文主要是针对自己在实际的协议分析过程中遇到的X-Requested-With头域进行了分析,主要分析了该头域为什么会出现,以及在什么情况下出现。好像是同一个问题,但是细究还是有所不同。  最近在报文抓包的时候遇到了...
  • Expected Number with value XX, got String with value "XX" 在使用element的进度条的时候,出现了这个问题,发现我的width设置属性是width=“66”, 出现这个原因是因为组件当着字符串处理了,则在width前面加上...
  • WITH AS 子查询

    千次阅读 2017-07-30 20:19:16
    WITH AS短语,也叫做子查询部分(subquery factoring),是用来定义一个SQL片断,该SQL片断会被整个SQL语句所用到。 1.with子句的返回结果存到用户的临时表空间中,只做一次查询,反复...3.前面with子句定义的查
  • catch up with用法

    千次阅读 2019-08-01 04:30:10
    How about I'll, uh, catch up with you in the Ice Age. ---《老友记》 第一季 第二集 ... 我们快点,赶上前面的那一伙人。 2.对...产生预期的坏影响(或恶果)Smoking will catch up with you soo...
  • python 使用 with open() as 读写文件

    万次阅读 多人点赞 2018-08-24 16:06:45
    总结:以后读写文件尽量使用with open语句,少使用f = open()语句   对于多个文件的读写,可以写成以下两种方式: 1、 with open('C:\Desktop\text.txt','r') as f: with open('C:\Desktop\text1....
  • 理解python的with语句

    千次阅读 多人点赞 2017-04-07 21:43:06
    一、with语句是什么 (1)有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,...
  • postgresql中的with查询

    千次阅读 2019-04-02 15:40:11
    WITH提供了一种编写辅助语句的方法,以便在较大的查询中使用。这些语句通常被称为公共表表达式或CTE,可以认为它们定义了仅为一个查询而存在的临时表。WITH子句中的每个辅助语句可以是SELECT、INSERT、UPDATE或...
  • 复制别人demo的布局,之后没有显示界面,下面提示Failed to load AppCompat ActionBar with unknown error解决方法:在style 里面的Theme.AppCompat.Light.DarkActionBar前面添加Base 之后就是这样的&lt;style name...
  • 一、基本语法 connect by递归查询基本...start with:表示以什么为根节点,不加限制可以写1=1,要以id为123的节点为根节点,就写为start with id =123 connect by:connect by是必须的,start with有些情况是可...
  • oracle with as子查询用法

    千次阅读 2014-10-16 17:00:53
    with table as 相当于建个临时表(用于一个语句中某些中间结果放在临时表空间的SQL语句),Oracle 9i 新增WITH语法,可以将查询中的子查询命名,放到SELECT语句的最前面
  • Hive中使用 with as 优化SQL

    万次阅读 多人点赞 2018-07-31 23:29:06
    当我们书写一些结构相对复杂的SQL语句时,可能某个子查询在多个层级多个地方存在重复使用的情况,这个时候我们可以使用 with as 语句将其独立出来,极大提高SQL可读性,简化SQL~ 注:目前 oracle、sql server、hive...
  • Python中with的用法

    万次阅读 多人点赞 2018-07-01 12:03:29
    With语句是什么? 有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。其中一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后...
  • SQL中的With语句

    千次阅读 2011-06-03 22:18:00
    可以使用with代替长的查询表,并在其后的查询中使用;...因为SQL本身也有with语句,所以这里的with前面的语句要用;表示语句结束。       WITH C AS ( SELECT [myroder] ,  SUM(mymoney) AS mymoney  FRO
  • python with as 用法

    千次阅读 2015-11-13 15:16:34
    这个语法是用来代替传统的try...finally语法的。  基本思想是with所求值的对象必须有一个__enter__()方法,一个__...当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。 举例: file = o
  • Java7里try-with-resources分析

    万次阅读 多人点赞 2014-01-18 22:18:34
    这个所谓的try-with-resources,是个语法糖。实际上就是自动调用资源的close()函数。和Python里的with语句差不多。 例如:   static String readFirstLineFromFile(String path) throws IOException { try ...
  • python中with的用法

    千次阅读 2017-11-23 10:53:05
    刚刚开始学python,今天在一个基础例子中看到了一行代码,觉得很有意思,就去研究了一下with open("../config/name_login.txt",'r') as f:其实这是python中的with语句,类似于php中的try()……catch(),主要是用来...
  • 论文:Single-Shot Object Detection with Enriched Semantics 论文链接:https://arxiv.org/abs/1712.00433 Detection with Enriched Semantics(DES)是CVPR2018的文章,基于SSD做改进,也是为了解决SSD中对于小...
  • SQL With cube

    千次阅读 2009-05-05 16:28:00
    cube运算符在 SELECT 语句的 GROUP BY 子句中指定。该语句的选择列表应包含维度列和聚合...先看下表:我们以id聚合查询出平均分这一条SQL语句与上面唯一不同之处即为多了后面的 with cube,而结果却是比前面更多了一条
  • Oracle with..as使用方法

    千次阅读 2018-10-27 17:20:06
    with..as关键字,是以‘with’关键字开头的sql语句,在实际工作中,我们经常会遇到同一个查询sql会同时查询多个相同的结果集,即sql一模一样,这时候我们可以将这些相同的sql抽取出来,使用with..as定义。with..as...
  • 1、with table as 相当于建个临时表(用于一个语句中某些中间结果放在临时表空间的SQL语句),Oracle 9i 新增WITH语法,可以将查询中的子查询命名,放到SELECT语句的最前面。 语法就是 with tempname as (select .....
  • oracle with子句

    千次阅读 2012-09-18 10:17:55
    以例子学习withwith --查询部门和部门的总薪水 dept_costs as ( select d.department_name,sum(e.salary) dept_total from departments d,employees e where d.dep
  • python上下文管理器ContextLib及with语句

    千次阅读 2016-01-01 12:30:42
    http://blog.csdn.net/pipisorry/article/details/50444736with语句with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from __future__ import with_statement 导入后才可以使用),从...
  • scala的extend和with

    千次阅读 2016-12-09 21:01:58
    最近在学习scala语言,记录下学习心得。 scala的extend和with是怎么用的? 1extend后面可以接类和特质(trait) class A{ } trait B{ ...2如果 extends和with同时使用则类比如放在前面 比如: class W

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 563,207
精华内容 225,282
关键字:

with前面跟什么