精华内容
下载资源
问答
  • with语句的用法: with context_expression [as target(s)]: with-body  context_expression为上下文表达式,该表达式需返回一个带 上下文管理器的对象,即该对象中实现了__enter()__和__exit()__方法  with...

    with语句的用法:

    with context_expression [as target(s)]:
    
        with-body

     context_expression为上下文表达式,该表达式需返回一个带

    上下文管理器的对象,即该对象中实现了__enter()__和__exit()__方法

     with-body中为执行代码块

    with语句首先执行context_expression,返回一个带上下文管理器的对象,

    接着执行返回对象中的__enter()__方法,若有as子句,则将__enter()__

    方法返回的值赋值给target(s),然后执行with-body中的代码块,最后执行

    context_expression返回对象中的__exit()__方法。例如:

    import requests
    
    r = requests.get("https://github.com/favicon.ico")
    
    with open('favicon.ico','wb') as f: #用open()方法打开一个文件,若无则创建 方法返回值赋给f
        f.write(r.content)

    With 后的open()方法会返回一个文件对象,该对象含上下文管理器,with获得open()对象后,调用对象

    中的__enter()__方法,open中的该方法返回的值为该对象本身,之后将open对象赋值给as后的变量f;

    接着执行with-body中的代码块f.write(r.content);执行完后,再执行open对象中的__exit()__方法,该方法

    会关闭open对象,即__exit()__方法中又调用了open().close()方法。

    with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

     

    参考文档 :https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

    展开全文
  • JavaScript中 with用法

    万次阅读 多人点赞 2018-03-28 12:50:09
      说起js中的with关键字,很多小伙伴们的第一印象可能就是with关键字的作用在于改变作用域,然后最关键的一点是不推荐使用with关键字。听到不推荐with关键字后,我们很多人都会忽略掉with关键字,认为不要去管它用...

    文章是本人大三期间的学习笔记,一些论断取自书籍和网上博客,碍于当时的技术水平有一些写得不够好的地方,可以在评论处理智讨论~

    说起js中的with关键字,很多小伙伴们的第一印象可能就是with关键字的作用在于改变作用域,然后最关键的一点是不推荐使用with关键字。听到不推荐with关键字后,我们很多人都会忽略掉with关键字,认为不要去管它用它就可以了。但是有时候,我们在看一些代码或者面试题的时候,其中会有with关键字的相关问题,很多坑是你没接触过的,所以还是有必要说说with这一个关键字。

    with的基本用法


    with 语句的原本用意是为逐级的对象访问提供命名空间式的速写方式. 也就是在指定的代码区域, 直接通过节点名称调用对象。

    with 通常被当做重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。

    比如,目前现在有一个这样的对象:

    var obj = {
    	a: 1,
    	b: 2,
    	c: 3
    };
    

    如果想要改变 obj 中每一项的值,一般写法可能会是这样:

    // 重复写了3次的“obj”
    obj.a = 2;
    obj.b = 3;
    obj.c = 4;
    

    而用了 with 的写法,会有一个简单的快捷方式

    with (obj) {
    	a = 3;
    	b = 4;
    	c = 5;
    }
    

    在这段代码中,使用了 with 语句关联了 obj 对象,这就以为着在 with 代码块内部,每个变量首先被认为是一个局部变量,如果局部变量与 obj 对象的某个属性同名,则这个局部变量会指向 obj 对象属性。

    with的弊端


    在上面的例子中,我们可以看到,with 可以很好地帮助我们简化代码。但是为什么不推荐使用呢?下面我们来说说with的缺点:

    导致数据泄漏

    我们来看下面的这部分代码

    function foo(obj) {
    	with (obj) {
    		a = 2;
    	}
    }
    
    var o1 = {
    	a: 3
    };
    
    var o2 = {
    	b: 3
    }
    
    foo(o1);
    console.log(o1.a);	//2
    
    foo(o2);
    console.log(o2.a);	//underfined
    console.log(a);		//2,a被泄漏到全局作用域上
    

    首先,我们来分析上面的代码。例子中创建了 o1 和 o2 两个对象。其中一个有 a 属性,另外一个没有。foo(obj) 函数接受一个 obj 的形参,该参数是一个对象引用,并对该对象引用执行了 with(obj) {...}。在 with 块内部,对 a 有一个词法引用,实际上是一个 LHS引用,将 2 赋值给了它。

    当我们将 o1 传递进去,a = 2 赋值操作找到了 o1.a 并将 2 赋值给它。而当 o2 传递进去,o2 并没有 a 的属性,因此不会创建这个属性,o2.a 保持 undefined。

    但为什么对 o2的操作会导致数据的泄漏呢?

    这里需要回到对 LHS查询 的机制问题(详情可移步 JavaScript中的LHS和RHS查询)。

    当我们传递 o2 给 with 时,with 所声明的作用域是 o2, 从这个作用域开始对 a 进行 LHS查询。o2 的作用域、foo(…) 的作用域和全局作用域中都没有找到标识符 a,因此在非严格模式下,会自动在全局作用域创建一个全局变量),在严格模式下,会抛出ReferenceError 异常。

    另一个不推荐 with 的原因是。在严格模式下,with 被完全禁止,间接或非安全地使用 eval(…) 也被禁止了。

    性能下降

    with 会在运行时修改或创建新的作用域,以此来欺骗其他在书写时定义的词法作用域。with 可以使代码更具有扩展性,虽然有着上面的数据泄漏的可能,但只要稍加注意就可以避免,难道不是可以创造出很好地功能吗?

    答案是否定的,具体原因我们先来看下面的这部分代码。

    下面代码可以直接复制出去运行

    <script>
    function func() {
    	console.time("func");
    	var obj = {
    		a: [1, 2, 3]
    	};
    	for(var i = 0; i < 100000; i++)
    	{
    		var v = obj.a[0];
    	}
    	console.timeEnd("func");
    }
    func();
    
    function funcWith() {
    	console.time("funcWith");
    	var obj = {
    		a: [1, 2, 3]
    	};
    	with(obj) {
    		for(var i = 0; i < 100000; i++) {
    			var v = a[0];
    		}
    	}
    	console.timeEnd("funcWith");
    }
    
    funcWith();
    </script>
    

    接着是,测试效果:

    这里写图片描述

    在处理相同逻辑的代码中,没用 with 的运行时间仅为 4.63 ms。而用 with 的运用时间长达 81.87ms。

    这是为什么呢?

    原因是 JavaScript 引擎会在编译阶段进行数项的性能优化。其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。

    但如果引擎在代码中发现了 with,它只能简单地假设关于标识符位置的判断都是无效的,因为无法知道传递给 with 用来创建新词法作用域的对象的内容到底是什么。

    最悲观的情况是如果出现了 with ,所有的优化都可能是无意义的。因此引擎会采取最简单的做法就是完全不做任何优化。如果代码大量使用 with 或者 eval(),那么运行起来一定会变得非常慢。无论引擎多聪明,试图将这些悲观情况的副作用限制在最小范围内,也无法避免如果没有这些优化,代码会运行得更慢的事实

    展开全文
  • axios基本用法

    万次阅读 多人点赞 2018-03-28 14:23:50
    //config { // `url` 是用于请求的服务器 URL url: '/user', // `method` 是创建请求时使用方法 method: 'get', // 默认是 get // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。 // 它可以通过...

    一.axios

    1.什么是axios

    axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端。简单的理解就是ajax的封装

    它本身具有以下特征:

     

         a.从浏览器中创建 XMLHttpRequest
         b.从 node.js 发出 http 请求
         c.支持 Promise API
         e.拦截请求和响应
         f.转换请求和响应数据
        g.取消请求
        h.自动转换JSON数据

     

        i.客户端支持防止 CSRF/XSRF

    2.安装

     nodeJs + webpack+vue+ element ui 环境安装

    二.axios  API

    (1).向 axios 传递相关配置来创建请求

    1.axios(config)
    // 发送 POST 请求
    axios({
      method: 'post',
      url: '/user/12345',
      data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
      }
    });
    
    2.axios(url[, config])
    // 发送 GET 请求(默认的方法)
    axios('/user/12345');

    (2).axios提供了一下几种请求方式

    1.axios.get(url[, config])  执行 GET 请求
    	eg:
    
    	// 向具有指定ID的用户发出请求
    	axios.get('/user?ID=12345')
    	  .then(function (response) {
    		console.log(response);
    	  })
    	  .catch(function (error) {
    		console.log(error);
    	  });
    	  
    	// 也可以通过 params 对象传递参数
    	axios.get('/user', {
    		params: {
    		  ID: 12345
    		}
    	  })
    	  .then(function (response) {
    		console.log(response);
    	  })
    	  .catch(function (error) {
    		console.log(error);
    	  });
    
    2.axios.post(url[, data[, config]]) 执行 POST 请求
    	eg:
    	axios.post('/user', {
    		firstName: 'Fred',
    		lastName: 'Flintstone'
    	  })
    	  .then(function (response) {
    		console.log(response);
    	  })
    	  .catch(function (error) {
    		console.log(error);
    	  });
    3.axios.request(config)
    
    4.axios.head(url[, config])
    
    5.axios.delete(url[, config])
    
    6.axios.put(url[, data[, config]])
    
    7.axios.patch(url[, data[, config]])
    
    8.axios.all(iterable)执行多个并发请求
    
        eg:
    		function getUserAccount() {
    		  return axios.get('/user/12345');
    		}
    
    		function getUserPermissions() {
    		  return axios.get('/user/12345/permissions');
    		}
    
    		axios.all([getUserAccount(), getUserPermissions()])
    		  .then(axios.spread(function (acct, perms) {
    			// 两个请求现在都执行完成
    		  }));
    9.axios.spread(callback)
    
    
    注意:处理并发请求的助手函数axios.all(iterable)      axios.spread(callback)

     

    (3).请求配置

     

    这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法。

    //config
    
    {
      // `url` 是用于请求的服务器 URL
      url: '/user',
    
      // `method` 是创建请求时使用的方法
      method: 'get', // 默认是 get
    
      // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
      // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
      baseURL: 'https://some-domain.com/api/',
    
      // `transformRequest` 允许在向服务器发送前,修改请求数据
      // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
      // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
      transformRequest: [function (data) {
        // 对 data 进行任意转换处理
    
        return data;
      }],
    
      // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
      transformResponse: [function (data) {
        // 对 data 进行任意转换处理
    
        return data;
      }],
    
      // `headers` 是即将被发送的自定义请求头
      headers: {'X-Requested-With': 'XMLHttpRequest'},
    
      // `params` 是即将与请求一起发送的 URL 参数
      // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
      params: {
        ID: 12345
      },
    
      // `paramsSerializer` 是一个负责 `params` 序列化的函数
      // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
      paramsSerializer: function(params) {
        return Qs.stringify(params, {arrayFormat: 'brackets'})
      },
    
      // `data` 是作为请求主体被发送的数据
      // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
      // 在没有设置 `transformRequest` 时,必须是以下类型之一:
      // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
      // - 浏览器专属:FormData, File, Blob
      // - Node 专属: Stream
      data: {
        firstName: 'Fred'
      },
    
      // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
      // 如果请求话费了超过 `timeout` 的时间,请求将被中断
      timeout: 1000,
    
      // `withCredentials` 表示跨域请求时是否需要使用凭证
      withCredentials: false, // 默认的
    
      // `adapter` 允许自定义处理请求,以使测试更轻松
      // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
      adapter: function (config) {
        /* ... */
      },
    
      // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
      // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
      auth: {
        username: 'janedoe',
        password: 's00pers3cret'
      },
    
      // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
      responseType: 'json', // 默认的
    
      // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
      xsrfCookieName: 'XSRF-TOKEN', // default
    
      // `xsrfHeaderName` 是承载 xsrf token 的值的 HTTP 头的名称
      xsrfHeaderName: 'X-XSRF-TOKEN', // 默认的
    
      // `onUploadProgress` 允许为上传处理进度事件
      onUploadProgress: function (progressEvent) {
        // 对原生进度事件的处理
      },
    
      // `onDownloadProgress` 允许为下载处理进度事件
      onDownloadProgress: function (progressEvent) {
        // 对原生进度事件的处理
      },
    
      // `maxContentLength` 定义允许的响应内容的最大尺寸
      maxContentLength: 2000,
    
      // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
      validateStatus: function (status) {
        return status >= 200 && status < 300; // 默认的
      },
    
      // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
      // 如果设置为0,将不会 follow 任何重定向
      maxRedirects: 5, // 默认的
    
      // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
      // `keepAlive` 默认没有启用
      httpAgent: new http.Agent({ keepAlive: true }),
      httpsAgent: new https.Agent({ keepAlive: true }),
    
      // 'proxy' 定义代理服务器的主机名称和端口
      // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
      // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
      proxy: {
        host: '127.0.0.1',
        port: 9000,
        auth: : {
          username: 'mikeymike',
          password: 'rapunz3l'
        }
      },
    
      // `cancelToken` 指定用于取消请求的 cancel token
      // (查看后面的 Cancellation 这节了解更多)
      cancelToken: new CancelToken(function (cancel) {
      })
    }

     

    (4).响应结构

     

    某个请求的响应包含以下信息

    {
      // `data` 由服务器提供的响应
      data: {},
    
      // `status` 来自服务器响应的 HTTP 状态码
      status: 200,
    
      // `statusText` 来自服务器响应的 HTTP 状态信息
      statusText: 'OK',
    
      // `headers` 服务器响应的头
      headers: {},
    
      // `config` 是为请求提供的配置信息
      config: {}
    }
    使用 then 时,你将接收下面这样的响应:
    
    axios.get('/user/12345')
      .then(function(response) {
        console.log(response.data);
        console.log(response.status);
        console.log(response.statusText);
        console.log(response.headers);
        console.log(response.config);
      });

     

    (5).配置的默认值/defaults

     

    你可以指定将被用在各个请求的配置默认值

    1.全局的 axios 默认值
    axios.defaults.baseURL = 'https://api.example.com';
    axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    
    2.自定义实例默认值
    // 创建实例时设置配置的默认值
    var instance = axios.create({
      baseURL: 'https://api.example.com'
    });
    
    // 在实例已创建后修改默认值
    instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    
    3.配置的优先顺序
    配置会以一个优先顺序进行合并。这个顺序是:在 lib/defaults.js 找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者。
    这里是一个例子:
    
    // 使用由库提供的配置的默认值来创建实例
    // 此时超时配置的默认值是 `0`
    var instance = axios.create();
    
    // 覆写库的超时默认值
    // 现在,在超时前,所有请求都会等待 2.5 秒
    instance.defaults.timeout = 2500;
    
    // 为已知需要花费很长时间的请求覆写超时设置
    instance.get('/longRequest', {
      timeout: 5000
    });

     

    (6).拦截器

     

    在请求或响应被 then 或 catch 处理前拦截它们。

    // 添加请求拦截器
    axios.interceptors.request.use(function (config) {
        // 在发送请求之前做些什么
        return config;
      }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      });
    
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        return response;
      }, function (error) {
        // 对响应错误做点什么
        return Promise.reject(error);
      });
    1.如果你想在稍后移除拦截器,可以这样:
    var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
    axios.interceptors.request.eject(myInterceptor);
    2.可以为自定义 axios 实例添加拦截器
    var instance = axios.create();
    instance.interceptors.request.use(function () {/*...*/});

    (7).错误处理

    axios.get('/user/12345')
      .catch(function (error) {
        if (error.response) {
          // 请求已发出,但服务器响应的状态码不在 2xx 范围内
          console.log(error.response.data);
          console.log(error.response.status);
          console.log(error.response.headers);
        } else {
          // Something happened in setting up the request that triggered an Error
          console.log('Error', error.message);
        }
        console.log(error.config);
      });
    可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围。
    axios.get('/user/12345', {
      validateStatus: function (status) {
        return status < 500; // 状态码在大于或等于500时才会 reject
      }
    })

    请查看官网

    三.注意细节

    1. 引用 axios 时

    Vue.prototype.axios = axios  Vue.prototype.$axios = axios    Vue.prototype.$http = axios  其实是都一个东西,只是vue的原型链上加个变量(且变量不同),值是axios对象 。

    只是 一个是jquery封装过的异步调用方法    一个是vue推荐的第三方异步封装方法  他们都是调用的axios对象

    只是调用的时候 axios.post({..})   this.$axios.post({...})     this.$http.post({....})

    四.案例

    1.本地data.json(f放在src同级)

    {
    	"seller": {
    		"name": "粥品香坊(回龙观)",
    		"description": "蜂鸟专送",
    		"deliveryTime": 38,
    		"score": 4.2,
    		"serviceScore": 4.1,
    		"foodScore": 4.3,
    		"rankRate": 69.2,
    		"minPrice": 20,
    		"deliveryPrice": 4,
    		"ratingCount": 24,
    		"sellCount": 90,
    		"bulletin": "粥品香坊其烹饪粥料的秘方源于中国千年古法,在融和现代制作工艺,由世界烹饪大师屈浩先生领衔研发。坚守纯天然、0添加的良心品质深得消费者青睐,发展至今成为粥类的引领品牌。是2008年奥运会和2013年园博会指定餐饮服务商。",
    		"supports": [{
    			"type": 0,
    			"description": "在线支付满28减5"
    		}, {
    			"type": 1,
    			"description": "VC无限橙果汁全场8折"
    		}, {
    			"type": 2,
    			"description": "单人精彩套餐"
    		}, {
    			"type": 3,
    			"description": "该商家支持发票,请下单写好发票抬头"
    		}, {
    			"type": 4,
    			"description": "已加入“外卖保”计划,食品安全保障"
    		}],
    		"avatar": "http://static.galileo.xiaojukeji.com/static/tms/seller_avatar_256px.jpg",
    		"pics": ["http://fuss10.elemecdn.com/8/71/c5cf5715740998d5040dda6e66abfjpeg.jpeg?imageView2/1/w/180/h/180", "http://fuss10.elemecdn.com/b/6c/75bd250e5ba69868f3b1178afbda3jpeg.jpeg?imageView2/1/w/180/h/180", "http://fuss10.elemecdn.com/f/96/3d608c5811bc2d902fc9ab9a5baa7jpeg.jpeg?imageView2/1/w/180/h/180", "http://fuss10.elemecdn.com/6/ad/779f8620ff49f701cd4c58f6448b6jpeg.jpeg?imageView2/1/w/180/h/180"],
    		"infos": ["该商家支持发票,请下单写好发票抬头", "品类:其他菜系,包子粥店", "北京市昌平区回龙观西大街龙观置业大厦底商B座102单元1340", "营业时间:10:00-20:30"]
    	}
    }

    2.修改webpack-dev-conf.js

    最新的vue没有dev-server.js文件,如何进行后台数据模拟?

    //第一步
    const express = require('express')
    const app = express()//请求server
    var appData = require('../data.json')//加载本地数据文件
    var seller = appData.seller //获取对应的本地数据
    var goods = appData.goods
    var ratings = appData.ratings
    var apiRoutes = express.Router()
    app.use('/api', apiRoutes)//通过路由请求数据
    
    //第二步
    before(app) {  
    	app.get('/api/seller', (req, res) => {  
    		res.json({  
    			// 这里是你的json内容  
    			errno: 0,  
    			data: seller  
    		})  
    	}),
    	app.post('/api/seller', (req, res) => {  
    		res.json({  
    			// 这里是你的json内容  
    			errno: 0,  
    			data: seller  
    		})  
    	})
    }

    3.axios.vue

    <template>
    	<div>
    		<h1>axios基础介绍</h1>
    		<button @click="get">get请求</button>
    		<button @click="post">post请求</button>
    		<button @click="http">aixos</button>
    		<p>{{msg}}</p>
    	</div>
    </template>
    
    <script>
    import axios from 'axios'
    export default {
    	data () {
    		return {
    			msg:'',
    		}
    	},
    	created(){
    		//全局拦截器
    		axios.interceptors.request.use(function (config) {  
    		    // 在发送请求之前做些什么  
    		    console.log('config')
    		    console.log(config)
    		    return config;  
    		}, function (error) {  
    		    // 对请求错误做些什么  
    		    return Promise.reject(error);  
    		}); 
    	},
    	methods: {
    		get(){
    			//1.简单的获取
    			// axios.get("/api/seller").then(res =>{
    			// 	this.msg = res;
    			// })
    			//2.传参数
    			axios.get("/api/seller",{
    				//传参数
    				params:{userid:"999"},
    				//请求头部
    				headers:{
    					token:"jack"
    				}
    			}).then(res =>{
    				this.msg = res;
    			}).catch(function(error){
    				//获取错误
    				console.log("error:"+error)
    			})
    		},
    		post(){
    			axios.post("/api/seller",{
    				//传参数
    					userid:"888"
    				},{
    					headers:{//请求头部
    					token:"tom"
    				}
    			}).then(res =>{
    				this.msg = res;
    			}).catch(function(error){
    				//获取错误
    				console.log("error:"+error)
    			})
    		},
    		http(){
    			//注意:get  传参是params   post传参是data
    			axios({
    				url:"/api/seller",
    				methods:"get",
    				params:{
    					userid:"101"
    				},
    				headers:{
    					token:"http-test"
    				}
    			}).then(res =>{
    				this.msg = res;
    			})
    		}
    
    	}
    }
    </script>
    
    <style  lang="scss">
    </style>

     

     

     

     

    展开全文
  • Python中with用法

    万次阅读 多人点赞 2018-07-01 12:03:29
    之前再遇到with语句在文件操作上的用法非常巧妙,以前不太熟悉,看的时候也产生一些困惑 With语句是什么? 有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理...

    之前再遇到with语句在文件操作上的用法非常巧妙,以前不太熟悉,看的时候也产生一些困惑

    With语句是什么?

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

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

    这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

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

    这段代码运行良好,但是太冗长。这时候with便体现出了优势。 除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

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

    是不是很简单?
    但是如果对with工作原理不熟悉的通许可能会和刚才的我一样,不懂其中原理
    那么下面我们简单看一下with的工作原理

    with是如何工作的?

    基本思想是:with所求值的对象必须有一个enter()方法,一个exit()方法。

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

    下面是一个例子

    ######################
    ########with()##########
    ######################
    class Sample:
        def __enter__(self):
            print("in __enter__")
    
            return "Foo"
    
        def __exit__(self, exc_type, exc_val, exc_tb):
                        #exc_type: 错误的类型 
                        #exc_val: 错误类型对应的值 
                        #exc_tb: 代码中错误发生的位置 
            print("in __exit__")
    
    def get_sample():
        return Sample()
    with get_sample() as sample:
        print("Sample: " ,sample)
    

    运行代码,输出如下
    这里写图片描述

    分析运行过程:

    1. 进入这段程序,首先创建Sample类,完成它的两个成员函数enter ()、exit()的定义,然后顺序向下定义get_sample()函数.
    2. 进入with语句,调用get_sample()函数,返回一个Sample()类的对象,此时就需要进入Sample()类中,可以看到

          1. __enter__()方法先被执行
          2. __enter__()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample'
          3. 执行with中的代码块,打印变量"sample",其值当前为 "Foo"
          4. 最后__exit__()方法被调用
      

    完整执行细节的调试过程请看gif:

    这里写图片描述

    这里只做了有限的简单说明,关于python中with用法详细参考:
    浅谈 Python 的 with 语句
    python的with用法

    展开全文
  • python with as 用法

    千次阅读 2015-11-13 15:16:34
    基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。 紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被...
  • python中with用法

    千次阅读 2017-11-23 10:53:05
    刚刚开始学python,今天在一个基础例子中看到了一行代码,觉得很有意思,就去研究了一下with open("../config/name_login.txt",'r') as f:其实这是python中的with语句,类似于php中的try()……catch(),主要是用来...
  • with关键字用法详解

    千次阅读 2017-06-12 17:59:28
    1.定义 Python’s with statement provides a very convenient way of dealing with the situation where you have to do a setup and teardown to make something happen. A very good example for this is the ...
  • sql start with用法

    千次阅读 2019-04-22 12:20:47
    我们经常会将一个比较复杂的目录树存储到一个表中。或者将一些部门存储到一个表中...这个时候你就会用到connect by prior start with。 connect by 是结构化查询中用到的,其基本语法是:  select ... from tablen...
  • DB2 with的定义与用法

    千次阅读 2018-08-21 10:20:10
    1.with理解与基本用法 说起WITH 语句,除了那些第一次听说WITH语句的人,大部分人都觉得它是用来做递归查询的。其实那只是它的一个用途而已, 它的本名正如我们标题写的那样,叫做:公共表表达式(Common Table...
  • WITH AS的用法

    千次阅读 2018-08-21 13:29:40
    一、WITH AS的含义   WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在...
  • Python学习笔记 --- with as 使用方法
  • Python中With用法

    千次阅读 2016-12-03 20:05:35
    With语句是什么?Python’s with statement provides a very convenient way of dealing with the situation where you have to do a setup and teardown to make something happen. A very good example for this ...
  • python中with as 用法

    千次阅读 多人点赞 2014-11-24 17:55:01
    with as和try except finally语句
  • 参考文章:python中with用法
  • sql的 WITH TIES用法

    2011-01-08 16:56:00
     这几天学习一下《Microsoft+SQL+Server+2005技术内幕:T-SQL查询》一书,突然看到top with ties ,以前都是用top来取查询结果集排序后去前几条记录,查了一下资料,原来它的用法如下。  WITH TIES ...
  • oracle 中start with用法

    千次阅读 2013-12-10 12:26:22
    基本用法~~~~~~~~~~~~~~~~~~~~~~ SELECT * FROM tree -- where 子句 , 若有,只是过滤最终结果的作用 START WITH father = '爷爷' -- 从 father 为 '爷爷' 的 那一条记录开始 -- 若有 nocyle 关键字, 则不走环, ...
  • sgdisk基本用法

    万次阅读 2017-07-28 17:09:55
    sgdisk基本用法简介sgdisk是Linux下操作GPT分区的工具,就像fdisk是操作MBR分区的工具。关于GPT和MBR的区别请参考: ...
  • Oracel中Start with 用法

    万次阅读 2018-07-13 16:24:17
    一,基本语法SELECT ... FROM + 表名 START WITH + 条件1CONNECT BY PRIOR + 条件2WHERE + 条件3条件1:是根节点的限定语句,当然可以放宽限定条件,以取得多个根节点,也就是多棵树;在连接关系中,除了可以...
  • tensorflow基本用法示例

    千次阅读 2017-02-20 18:46:20
    关于tensorflow的基本用法,教程详见: TensorFlow官方文档中文版——基本使用, ...由于版本更新,原教程的一些代码已不能使用,下面是修改之后的tensorflow基本用法示例。1. add_operationimport te
  • oracle中Start with 用法

    千次阅读 2019-04-09 14:28:24
    一,基本语法 SELECT … FROM + 表名 START WITH + 条件1 CONNECT BY PRIOR + 条件2 WHERE + 条件3 条件1:是根节点的限定语句,当然可以放宽限定条件,以取得多个根节点,也就是多棵树;在连接关系中,除了可以使用...
  • laravel model基本使用方法

    千次阅读 2018-03-16 14:52:36
    model 基本方法 “` $orders = App\Models\TestModel::all(); foreach (ordersasordersasorders as order) { $order-&gt;users-&gt;get();} 如果一个订单有25个用户,将导致有26条SQL语句,使用...
  • Guice基本用法

    千次阅读 2016-10-19 19:29:16
    文章对Guice做了简单的介绍,主要展示了Guice的基本用法以及相关概念
  • sql 中startwith 用法

    万次阅读 2016-09-05 14:48:55
    我们经常会将一个比较复杂的目录树存储到一个表中。或者将一些部门存储到一个表...connect by 是结构化查询中用到的,其基本语法是:  select ... from tablename start with 条件1  connect by prior 条件2  where
  • Axios基本用法

    千次阅读 2017-06-01 14:51:30
    vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios,前一段时间用了一下,现在说一下它的基本用法。 首先就是引入axios,如果你使用es6,只需要安装axios模块之后 import axios from 'axios...
  • requireJS的基本用法

    万次阅读 热门讨论 2016-07-06 22:26:01
    在开始的时候对这个框架不是很懂,因为里面有很多平台自己封装的东西,所以在理解起来不是很容易,经过这一段时间在项目中的运用有了一定的理解,下面先来总结总结一下其中的一个技术点——RequireJS的基本用法。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 584,165
精华内容 233,666
关键字:

with的基本用法