- 浏览: 252679 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
runjia1987:
cpu 100%,是因为读=-1时,没有解注册OP_READ, ...
java nio网络编程的一点心得 -
two_plus:
按照你的例子 服务端变成读循环了...
java nio网络编程的一点心得 -
ilovemyyang:
我也遇到同样的空循环问题,也是百度才找到了的,楼主给力哦
java nio网络编程的一点心得 -
高攀sky:
Python发邮件 -
fobdddf:
fobdddf 写道朋友你好,我试了一下数组的那个例子,反汇编 ...
读《深入理解计算机系统》
我已经好几次碰到这样的错误了,每次碰到都花费我大量的时间,下面总结下我所犯的错误,希望对大家也有帮助。
闭包
我想抓取一系列的网页,抓取网页很慢,然后对网页内容进行处理,为了提高速度,我启动了多个线程去抓。以下是其代码:
代码很简单,对每个url都启动一个线程,线程启动时运行_fetch函数,_fetch函数是个闭包,因为它引用了循环变量url,我使用time.sleep()来模拟抓取网页的过程。我们期望url在每个_fetch函数内有不同值,且在函数内保持不变,但实际上不是,上述程序输出如下结果:
注意到process content全部输出的都是baidu。为什么会有这个结果?这是因为实际上每个_fetch引用的是同一个变量,随着循环的进行,url的值在不断的变化。线程刚启动时url值还没来得及改变,但是抓取网页完成后,循环已经结束了,url保持为最后一次循环的值,即http://www.baidu.com。怎么解决这个问题呢?在_fetch函数内部先将url赋给一个局部变量的方式是有问题的:
虽然它的输出结果在我的机器上是正确的,但却有可能在其它机器上失败,这是因为线程的启动可能在这次循环体结束之后,这样有可能会抓取重复的url。一种方式是利用命名参数来保持当前循环时url值:
这种方式起作用是因为每个函数会保持命令参数的默认值,每次循环时的url被保持在_fetch函数内,不带参数调用它时,url为函数本身保持的url默认值,而不是循环变量url。仅仅对这个示例,更简单的方式是直接将url传给线程的构造函数,但这种方式并不总有效。
变量覆盖方法
我要写一个让用户输入验证码的引擎,验证码内容从一个url处获得,两次让用户输入验证码。以下是其代码:
代码看起来很正常,但运行时却显示错误:
异常是在第二次调用e.captcha()方法时出现的,错误很令人莫名其妙。问题原因是我们在第6行将用户输入结果保存在self.captcha中了,它和方法名字一样,所以第一次调用完成之后,e.capcha就变成用户输入的字符串了,所以在第11行再次调用e.captcha()方法时,它实际上调用str.__call__()方法,而str没有这个方法,所以就出现上面的异常。有Java,C++或者C#背景的人比较容易上犯这个错误,在这些语言中变量和方法属于不同的命名空间,一方不会覆盖另一方。而在python等函数编程语言中,函数就是第一类对象,不再区分方法和变量,同名的变量会覆盖同名的方法,反之亦然。解决方法很简单,将captcha方法重命名为get_captcha就可以了。
list comprehension
我要导入一个联系人列表,每个联系人有name, mobile, address, im, 并且可能有多个备份mobile,假设每个字段以空格分开,多个备份mobile之前以逗号分开。以下是其代码:
你可能会想结果会输出:
但实际输出:
这是因为第12行使用了list comprehension,其中使用变量名称和第9行使用的变量名称相同,都为mobile,在python中这两个是同一个变量,使用list comprehension会改变mobile,最终结果为backup_mobiles最后一个元素的值。有Java, C++等背景的人也容易犯这个错误,因为很容易将list comprehension理解成:
而在这些语言中,mobile属于for循环里的局部变量,不会覆盖外面的同名变量(只是会隐藏)。但在python中不同,两者是同一个变量,解决方法很简单将list comprehension中的mobile变量改成短名m,就像循环变量通常使用短名一样,list comprehension也最好使用短名,表示它们的作用域很小,不容易覆盖外围变量(或者覆盖了也没事)。
(完)
闭包
我想抓取一系列的网页,抓取网页很慢,然后对网页内容进行处理,为了提高速度,我启动了多个线程去抓。以下是其代码:
import sys import threading import time urls = [ 'http://www.google.com', 'http://www.sina.com.cn', 'http://www.baidu.com' ] for url in urls: def _fetch(): sys.stdout.write('fetch from: %s\n' % url) time.sleep(1) # 模拟获取网页 sys.stdout.write('process content from: %s\n' % url) threading.Thread(target=_fetch).start()
代码很简单,对每个url都启动一个线程,线程启动时运行_fetch函数,_fetch函数是个闭包,因为它引用了循环变量url,我使用time.sleep()来模拟抓取网页的过程。我们期望url在每个_fetch函数内有不同值,且在函数内保持不变,但实际上不是,上述程序输出如下结果:
fetch from: http://www.google.com fetch from: http://www.sina.com.cn fetch from: http://www.baidu.com process content from: http://www.baidu.com process content from: http://www.baidu.com process content from: http://www.baidu.com
注意到process content全部输出的都是baidu。为什么会有这个结果?这是因为实际上每个_fetch引用的是同一个变量,随着循环的进行,url的值在不断的变化。线程刚启动时url值还没来得及改变,但是抓取网页完成后,循环已经结束了,url保持为最后一次循环的值,即http://www.baidu.com。怎么解决这个问题呢?在_fetch函数内部先将url赋给一个局部变量的方式是有问题的:
for url in urls: def _fetch(): _url = url sys.stdout.write('fetch from: %s\n' % _url) time.sleep(1) # 模拟获取网页 sys.stdout.write('process content from: %s\n' % _url) threading.Thread(target=_fetch).start()
虽然它的输出结果在我的机器上是正确的,但却有可能在其它机器上失败,这是因为线程的启动可能在这次循环体结束之后,这样有可能会抓取重复的url。一种方式是利用命名参数来保持当前循环时url值:
for url in urls: def _fetch(url=url): sys.stdout.write('fetch from: %s\n' % url) time.sleep(1) # 模拟获取网页 sys.stdout.write('process content from: %s\n' % url) threading.Thread(target=_fetch).start()
这种方式起作用是因为每个函数会保持命令参数的默认值,每次循环时的url被保持在_fetch函数内,不带参数调用它时,url为函数本身保持的url默认值,而不是循环变量url。仅仅对这个示例,更简单的方式是直接将url传给线程的构造函数,但这种方式并不总有效。
for url in urls: def _fetch(url): sys.stdout.write('fetch from: %s\n' % url) time.sleep(1) # 模拟获取网页 sys.stdout.write('process content from: %s\n' % url) threading.Thread(target=_fetch, args=(url,)).start()
变量覆盖方法
我要写一个让用户输入验证码的引擎,验证码内容从一个url处获得,两次让用户输入验证码。以下是其代码:
class Engine(object): def captcha(self, url): '''从url处获得验证码''' # get captcha from url # ... self.captcha = raw_input('Enter the captcha: ') return self e = Engine() e.captcha('http://website/captcha') # first time print 'You entered captcha: %s' % e.captcha e.captcha('http://website/captcha') # second time print 'You entered captcha: %s' % e.captcha
代码看起来很正常,但运行时却显示错误:
Enter the captcha: <<ea859>> # 输入验证码 You entered captcha: <<ea859>> Traceback (most recent call last): File "test.py", line 11, in <module> e.captcha('http://website/captcha') # second time TypeError: 'str' object is not callable
异常是在第二次调用e.captcha()方法时出现的,错误很令人莫名其妙。问题原因是我们在第6行将用户输入结果保存在self.captcha中了,它和方法名字一样,所以第一次调用完成之后,e.capcha就变成用户输入的字符串了,所以在第11行再次调用e.captcha()方法时,它实际上调用str.__call__()方法,而str没有这个方法,所以就出现上面的异常。有Java,C++或者C#背景的人比较容易上犯这个错误,在这些语言中变量和方法属于不同的命名空间,一方不会覆盖另一方。而在python等函数编程语言中,函数就是第一类对象,不再区分方法和变量,同名的变量会覆盖同名的方法,反之亦然。解决方法很简单,将captcha方法重命名为get_captcha就可以了。
class Engine(object): def get_captcha(self, url): '''从url处获得验证码''' # get captcha from url # ... self.captcha = raw_input('Enter the captcha: ') return self e = Engine() e.get_captcha('http://website/captcha') # first time print 'You entered captcha: %s' % e.captcha e.get_captcha('http://website/captcha') # second time print 'You entered captcha: %s' % e.captcha
list comprehension
我要导入一个联系人列表,每个联系人有name, mobile, address, im, 并且可能有多个备份mobile,假设每个字段以空格分开,多个备份mobile之前以逗号分开。以下是其代码:
from StringIO import StringIO def is_mobile(mobile): return len(mobile) == 11 def import_contacts(file): for line in file.readlines(): parts = line.strip().split() name = parts[0] mobile = parts[1] address = parts[2] im = parts[3] backup_mobiles = [ mobile for mobile in parts[4].split(',') if is_mobile(mobile) ] print 'importing contact: %s, mobile=%s' % (name, mobile) import_contacts(StringIO('''marlon 13511002222 beijing marlon@gmail.com 13711112222,13822224444'''))
你可能会想结果会输出:
importing contact: marlon, mobile=13511002222
但实际输出:
importing contact: marlon, mobile=13822224444
这是因为第12行使用了list comprehension,其中使用变量名称和第9行使用的变量名称相同,都为mobile,在python中这两个是同一个变量,使用list comprehension会改变mobile,最终结果为backup_mobiles最后一个元素的值。有Java, C++等背景的人也容易犯这个错误,因为很容易将list comprehension理解成:
List<String> backup_mobiles = new ArrayList<String>(); for (String mobile: parts[4].split(",")) { backup_mobiles.add(mobile); }
而在这些语言中,mobile属于for循环里的局部变量,不会覆盖外面的同名变量(只是会隐藏)。但在python中不同,两者是同一个变量,解决方法很简单将list comprehension中的mobile变量改成短名m,就像循环变量通常使用短名一样,list comprehension也最好使用短名,表示它们的作用域很小,不容易覆盖外围变量(或者覆盖了也没事)。
from StringIO import StringIO def is_mobile(mobile): return len(mobile) == 11 def import_contacts(file): for line in file.readlines(): parts = line.strip().split() name = parts[0] mobile = parts[1] address = parts[2] im = parts[3] backup_mobiles = [ m for m in parts[4].split(',') if is_mobile(m) ] print 'importing contact: %s, mobile=%s' % (name, mobile) import_contacts(StringIO('''marlon 13511002222 beijing marlon@gmail.com 13711112222,13822224444'''))
(完)
发表评论
-
Python模板性能评测
2011-11-28 18:00 5588本篇主要是对django, jinja ... -
Mongodb内嵌文档插入性能评测
2011-11-20 18:03 11402Mongodb作为典型的文档数据库,支持内嵌文档和复杂的查询, ... -
支持通配符的DNS代理
2011-05-05 22:23 6989hosts文件可以手动配置一些域名的IP地址,它的优先级最高, ... -
在App Engine下运行Django 1.2
2011-03-20 22:12 1923我不知道App Engine是从什 ... -
实现简单的Future
2011-02-19 19:38 1611异步调用的困难之处我们不知道它什么时候会返回,通常的解决方法是 ... -
创建简单声明式python对象模型
2011-02-19 12:27 2729创建简单python声明式对象模型 要创建一个简单的Auth ... -
用RestrictedPython创建Python Sandbox
2011-02-13 17:35 2973众所周知在Python下可以 ... -
wxpython中工作线程与主线程交互
2011-01-15 23:56 6072在wxpython中,像其它GUI ... -
Python下Base64编码
2010-12-04 12:53 2592在Python下有Base64编码的库,可直接用,我自己写了个 ... -
Python中用MetaClass实现委托、不可变集合
2010-09-13 16:01 5316委托(delegate)是许多设计模式(如Decorator, ... -
用编程语言作数据库测试的配置
2010-09-11 11:25 1313在上一篇博客:django, mo ... -
django, mongodb与测试
2010-09-11 10:05 3309在django下很容易写测试,只需要继承DjangoTestC ... -
一个简单的Form向导实现
2010-06-20 18:42 1363Django的contrib中带了个FormWizard,但是 ... -
再一个用于调试Django模板的标签
2010-06-15 17:42 1835主要用于在Html中递归输出对象的属性,这对调试Django相 ... -
几个用于调试Django模板的标签
2010-06-15 17:18 4586Django模板有诸多限制,例如不能调用方法,不能执行任意的P ... -
探索Python下的property, classmethod, staticmethod的实现
2010-05-30 21:10 4106Python有几个内置方法poperty, classmeth ... -
Python农历公历转换
2010-04-24 17:38 2212实现中主要有两个方法,一个是get_lunar_date,它根 ... -
Python发邮件
2010-03-27 11:25 2368下面的代码的作用是将电子书作为附件发送到163邮箱。 ...
相关推荐
3. **大型标准库**:Python拥有一个庞大的标准库,为开发者提供了大量的内置函数和模块,覆盖了许多常见的编程任务。 4. **开源与活跃社区**:Python是一个开源项目,由Python软件基金会管理,并拥有一个非常活跃的...
书中的内容覆盖了Python的基础知识,包括变量、表达式、语句、函数、模块、字符串、列表、文件等,并通过大量的实例和练习来加深理解。 总结来说,《Think Python(中文版)》是一本为那些希望通过编程改善思维技能...
- **环境变量设置**:讲解了如何设置必要的环境变量以支持Python开发。 ##### 6.2 虚拟环境 - **虚拟环境简介**:介绍了虚拟环境的概念及其在Python开发中的作用。 - **创建与管理**:讲解了如何使用venv、...
此外,Python拥有大量的内置功能和第三方库,覆盖从数据分析、网络编程到自动化脚本等广泛的应用领域。通过学习Python,初学者可以逐渐理解编程的基本概念,如变量、循环、条件语句、函数等,并逐步深入到面向对象...
它由60个独立课程组成,覆盖了Python的基础语法到高级特性。 - **标签**:“Python”,表明该教程专门针对Python编程语言。 #### 二、知识点详解 - **【Python第1课】安装** - **主要内容**:介绍如何在不同操作...
- **主要内容**:本书提供了Python编程的基础知识,覆盖了变量、数据类型、控制结构、函数、模块等核心概念,并通过丰富的示例帮助读者理解这些概念的应用。 - **编写特点**:采用中英文对照的方式编写,既适合英语...
- **最佳实践**:分享作者在Python开发过程中积累的最佳实践和常见陷阱避免方法。 #### 六、作者简介与出版信息 - **作者**:André Dos Santos Lessa,具有多年Python开发经验的专业人士。 - **出版社**:Sams ...
### Python Guide:全面掌握Python开发的关键知识点 #### 一、概览 ...综上所述,《Python Guide》是一份内容丰富、覆盖广泛的Python学习资源,无论你是Python新手还是资深开发者,都可以从中受益匪浅。
课程还指出了一些Python初学者常见的小陷阱,如大小写敏感、缩进的重要性(Python的语法结构依赖于缩进,而不是花括号),以及如何正确处理字符串和变量等。 总的来说,这门课程的上半部分主要覆盖了Python的基础...
《如何像Python程序员一样思考》覆盖了计算机科学中的多个核心领域: 1. **编程基础**:从最基本的变量、数据类型到函数、循环等,本书提供了全面的介绍。 2. **数据结构与算法**:详细解释了数组、列表、字典等...
- **掌握Python基础知识**:从变量、数据类型到函数、模块,全面覆盖Python的核心概念。 - **培养编程思维**:学会分析问题、设计算法,并将其转化为代码,提高抽象思维能力和逻辑推理能力。 - **实践编程技能**:...
- **变量与数据类型**:介绍Python中的基本数据类型(如整型、浮点型、字符串)以及变量的概念。 - **控制结构**:讲解条件语句、循环语句等控制流程的方法。 - **函数**:讨论如何定义和调用函数,以及函数参数的...
除了上述快速入门教程之外,Pandas 还提供了丰富的教程资源,覆盖了从基础到高级的各个层次,帮助用户深入掌握 Pandas 的使用技巧。这些教程通常包含实际案例,让用户能够在实践中学习和应用所学知识。
错误地使用作用域可能导致意外的变量覆盖、未定义的变量引用等问题。在编写程序时,应遵循“最小作用域原则”,即尽量让变量的作用域尽可能小,以减少全局变量的使用,提高代码的可维护性和安全性。 在Python中,...
在实际应用中,可以将这个列表集成到自动化测试框架中,对输入处理函数进行覆盖测试,确保所有可能的异常情况都被妥善处理。此外,也可以作为编写输入验证规则和过滤器的参考,确保对用户输入进行充分的校验,减少因...
- **练习指南**:包含了一系列练习,覆盖了Python编程的基础知识,从简单的程序开始,逐渐过渡到更复杂的概念。 #### 四、具体知识点 1. **基础概念**: - **第1章**:介绍如何编写一个简单的Python程序,包括打印...
书中介绍了如何检查变量和数据结构、理解段错误(segmentation faults)和核心转储(core dumps)、了解程序为什么会崩溃或者抛出异常、使用断点(catchpoints)、便利变量(convenience variables)和人工数组...
它帮助用户理解SymPy中的一些重要概念,如等号使用、变量处理、符号表达式、特殊符号处理,以及如何在SymPy内部获取帮助。 文档的第四部分是SymPy模块的参考。这部分内容对SymPy的所有核心模块进行了详细介绍。模块...