python urllib2 详解

urllib2是Python的一个获取URLs(Uniform Resource Locators)的组件。他以urlopen函数的形式提供了一个非常简单的接口,
这是具有利用不同协议获取URLs的能力,他同样提供了一个比较复杂的接口来处理一般情况,例如:基础验证,cookies,代理和其他。
它们通过handlers和openers的对象提供。
urllib2支持获取不同格式的URLs(在URL的”:”前定义的字串,例如:”ftp”是”ftp:python.ort/”的前缀),它们利用它们相关网络协议(例如FTP,HTTP)
进行获取。这篇教程关注最广泛的应用–HTTP。
对于简单的应用,urlopen是非常容易使用的。但当你在打开HTTP的URLs时遇到错误或异常,你将需要一些超文本传输协议(HTTP)的理解。
最权威的HTTP文档当然是RFC 2616(http://rfc.net/rfc2616.html)。这是一个技术文档,所以并不易于阅读。这篇HOWTO教程的目的是展现如何使用urllib2,
并提供足够的HTTP细节来帮助你理解。他并不是urllib2的文档说明,而是起一个辅助作用。
获取 URLs
最简单的使用urllib2将如下所示
[codesyntax lang=”python”]

import urllib2 
response = urllib2.urlopen('http://python.org/') 
html = response.read()

[/codesyntax]
urllib2的很多应用就是那么简单(记住,除了”http:”,URL同样可以使用”ftp:”,”file:”等等来替代)。但这篇文章是教授HTTP的更复杂的应用。
HTTP是基于请求和应答机制的–客户端提出请求,服务端提供应答。urllib2用一个Request对象来映射你提出的HTTP请求,在它最简单的使用形式中你将用你要请求的
地址创建一个Request对象,通过调用urlopen并传入Request对象,将返回一个相关请求response对象,这个应答对象如同一个文件对象,所以你可以在Response中调用.read()。
[python]
import urllib2
req = urllib2.Request(‘http://www.voidspace.org.uk’)
response = urllib2.urlopen(req)
the_page = response.read()

[/codesyntax]
记得urllib2使用相同的接口处理所有的URL头。例如你可以像下面那样创建一个ftp请求。
req = urllib2.Request(‘ftp://example.com/’)
在HTTP请求时,允许你做额外的两件事。首先是你能够发送data表单数据,其次你能够传送额外的关于数据或发送本身的信息(“metadata”)到服务器,此数据作为HTTP的”headers”来发送。
接下来让我们看看这些如何发送的吧。
Data数据
有时候你希望发送一些数据到URL(通常URL与CGI[通用网关接口]脚本,或其他WEB应用程序挂接)。在HTTP中,这个经常使用熟知的POST请求发送。这个通常在你提交一个HTML表单时由你的浏览器来做。
并不是所有的POSTs都来源于表单,你能够使用POST提交任意的数据到你自己的程序。一般的HTML表单,data需要编码成标准形式。然后做为data参数传到Request对象。编码工作使用urllib的函数而非
urllib2。
[codesyntax lang=”python”]

import urllib 
import urllib2 
url = 'http://www.someserver.com/cgi-bin/register.cgi' 
values = {'name' : 'Michael Foord', 
          'location' : 'Northampton', 
          'language' : 'Python' } 
data = urllib.urlencode(values) 
req = urllib2.Request(url, data) 
response = urllib2.urlopen(req) 
the_page = response.read()

[/codesyntax]
记住有时需要别的编码(例如从HTML上传文件–看http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13 HTML Specification, Form Submission的详细说明)。
如ugoni没有传送data参数,urllib2使用GET方式的请求。GET和POST请求的不同之处是POST请求通常有”副作用”,它们会由于某种途径改变系统状态(例如提交成堆垃圾到你的门口)。
尽管HTTP标准说的很清楚POSTs通常会产生副作用,GET请求不会产生副作用,但没有什么可以阻止GET请求产生副作用,同样POST请求也可能不产生副作用。Data同样可以通过在Get请求
的URL本身上面编码来传送。
可看如下例子
[python:nogutter]
>>> import urllib2
>>> import urllib
>>> data = {}
>>> data[‘name’] = ‘Somebody Here’
>>> data[‘location’] = ‘Northampton’
>>> data[‘language’] = ‘Python’
>>> url_values = urllib.urlencode(data)
>>> print url_values
name=Somebody+Here&language=Python&location=Northampton
>>> url = ‘http://www.example.com/example.cgi’
>>> full_url = url + ‘?’ + url_values
>>> data = urllib2.open(full_url)

[/codesyntax]
Headers
我们将在这里讨论特定的HTTP头,来说明怎样添加headers到你的HTTP请求。
有一些站点不喜欢被程序(非人为访问)访问,或者发送不同版本的内容到不同的浏览器。默认的urllib2把自己作为“Python-urllib/x.y”(x和y是Python主版本和次版本号,例如Python-urllib/2.5),
这个身份可能会让站点迷惑,或者干脆不工作。浏览器确认自己身份是通过User-Agent头,当你创建了一个请求对象,你可以给他一个包含头数据的字典。下面的例子发送跟上面一样的内容,但把自身
模拟成Internet Explorer。
[codesyntax lang=”python”]

import urllib 
import urllib2 
url = 'http://www.someserver.com/cgi-bin/register.cgi' 
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' 
values = {'name' : 'Michael Foord', 
          'location' : 'Northampton', 
          'language' : 'Python' } 
headers = { 'User-Agent' : user_agent } 
data = urllib.urlencode(values) 
req = urllib2.Request(url, data, headers) 
response = urllib2.urlopen(req) 
the_page = response.read()

[/codesyntax]
response应答对象同样有两个很有用的方法。看下面的节info and geturl,我们将看到当发生错误时会发生什么。
Handle Exceptions处理异常
当urlopen不能够处理一个response时,产生urlError(不过通常的Python APIs异常如ValueError,TypeError等也会同时产生)。
HTTPError是urlError的子类,通常在特定HTTP URLs中产生。
URLError
通常,URLError在没有网络连接(没有路由到特定服务器),或者服务器不存在的情况下产生。这种情况下,异常同样会带有”reason”属性,它是一个tuple,包含了一个错误号和一个错误信息。
例如
[codesyntax lang=”python”]

>>> req = urllib2.Request('http://www.pretend_server.org') 
>>> try: urllib2.urlopen(req) 
>>> except URLError, e: 
>>>    print e.reason 
>>> 
(4, 'getaddrinfo failed')

[/codesyntax]
HTTPError
服务器上每一个HTTP 应答对象response包含一个数字”状态码”。有时状态码指出服务器无法完成请求。默认的处理器会为你处理一部分这种应答(例如:假如response是一个”重定向”,需要客户端从别的地址获取文档
,urllib2将为你处理)。其他不能处理的,urlopen会产生一个HTTPError。典型的错误包含”404″(页面无法找到),”403″(请求禁止),和”401″(带验证请求)。
请看RFC 2616 第十节有所有的HTTP错误码
HTTPError实例产生后会有一个整型’code’属性,是服务器发送的相关错误号。
Error Codes错误码
因为默认的处理器处理了重定向(300以外号码),并且100-299范围的号码指示成功,所以你只能看到400-599的错误号码。
BaseHTTPServer.BaseHTTPRequestHandler.response是一个很有用的应答号码字典,显示了RFC 2616使用的所有的应答号。这里为了方便重新展示该字典。(译者略)
当一个错误号产生后,服务器返回一个HTTP错误号,和一个错误页面。你可以使用HTTPError实例作为页面返回的应答对象response。这表示和错误属性一样,它同样包含了read,geturl,和info方法。
[codesyntax lang=”python”]

>>> req = urllib2.Request('http://www.python.org/fish.html') 
>>> try: 
>>>     urllib2.urlopen(req) 
>>> except URLError, e: 
>>>     print e.code 
>>>     print e.read() 
>>> 
404 

Error 404: File Not Found 
...... etc...

[/codesyntax]
Wrapping it Up包装
所以如果你想为HTTPError或URLError做准备,将有两个基本的办法。我则比较喜欢第二种。
第一个:
[codesyntax lang=”python”]

from urllib2 import Request, urlopen, URLError, HTTPError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except HTTPError, e: 
    print 'The server couldn/'t fulfill the request.' 
    print 'Error code: ', e.code 
except URLError, e: 
    print 'We failed to reach a server.' 
    print 'Reason: ', e.reason 
else: 
    # everything is fine

[/codesyntax]
注意:except HTTPError 必须在第一个,否则except URLError将同样接受到HTTPError。
第二个:
[codesyntax lang=”python”]

from urllib2 import Request, urlopen, URLError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except URLError, e: 
    if hasattr(e, 'reason'): 
        print 'We failed to reach a server.' 
        print 'Reason: ', e.reason 
    elif hasattr(e, 'code'): 
        print 'The server couldn/'t fulfill the request.' 
        print 'Error code: ', e.code 
else: 
    # everything is fine

[/codesyntax]
info and geturl
urlopen返回的应答对象response(或者HTTPError实例)有两个很有用的方法info()和geturl()
geturl — 这个返回获取的真实的URL,这个很有用,因为urlopen(或者opener对象使用的)或许
会有重定向。获取的URL或许跟请求URL不同。
info — 这个返回对象的字典对象,该字典描述了获取的页面情况。通常是服务器发送的特定头headers。目前是httplib.HTTPMessage 实例。
经典的headers包含”Content-length”,”Content-type”,和其他。查看Quick Reference to HTTP Headers(http://www.cs.tut.fi/~jkorpela/http.html)
获取有用的HTTP头列表,以及它们的解释意义。
Openers和Handlers
当你获取一个URL你使用一个opener(一个urllib2.OpenerDirector的实例,urllib2.OpenerDirector可能名字可能有点让人混淆。)正常情况下,我们
使用默认opener — 通过urlopen,但你能够创建个性的openers,Openers使用处理器handlers,所有的“繁重”工作由handlers处理。每个handlers知道
如何通过特定协议打开URLs,或者如何处理URL打开时的各个方面,例如HTTP重定向或者HTTP cookies。
如果你希望用特定处理器获取URLs你会想创建一个openers,例如获取一个能处理cookie的opener,或者获取一个不重定向的opener。
要创建一个 opener,实例化一个OpenerDirector,然后调用不断调用.add_handler(some_handler_instance).
同样,可以使用build_opener,这是一个更加方便的函数,用来创建opener对象,他只需要一次函数调用。
build_opener默认添加几个处理器,但提供快捷的方法来添加或更新默认处理器。
其他的处理器handlers你或许会希望处理代理,验证,和其他常用但有点特殊的情况。
install_opener 用来创建(全局)默认opener。这个表示调用urlopen将使用你安装的opener。
Opener对象有一个open方法,该方法可以像urlopen函数那样直接用来获取urls:通常不必调用install_opener,除了为了方便。
Basic Authentication 基本验证
为了展示创建和安装一个handler,我们将使用HTTPBasicAuthHandler,为了更加细节的描述本主题–包含一个基础验证的工作原理。
请看Basic Authentication Tutorial(http://www.voidspace.org.uk/python/articles/authentication.shtml)
当需要基础验证时,服务器发送一个header(401错误码) 请求验证。这个指定了scheme 和一个‘realm’,看起来像这样:Www-authenticate: SCHEME realm=”REALM”.
例如
Www-authenticate: Basic realm=”cPanel Users”
客户端必须使用新的请求,并在请求头里包含正确的姓名和密码。这是“基础验证”,为了简化这个过程,我们可以创建一个HTTPBasicAuthHandler的实例,并让opener使用这个
handler。
HTTPBasicAuthHandler使用一个密码管理的对象来处理URLs和realms来映射用户名和密码。如果你知道realm(从服务器发送来的头里)是什么,你就能使用HTTPPasswordMgr。
通常人们不关心realm是什么。那样的话,就能用方便的HTTPPasswordMgrWithDefaultRealm。这个将在你为URL指定一个默认的用户名和密码。这将在你为特定realm提供一个其他组合时
得到提供。我们通过给realm参数指定None提供给add_password来指示这种情况。
最高层次的URL是第一个要求验证的URL。你传给.add_password()更深层次的URLs将同样合适。
[codesyntax lang=”python”]

# 创建一个密码管理者 
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() 
# 添加用户名和密码 
# 如果知道 realm, 我们可以使用他代替 ``None``. 
top_level_url = "http://example.com/foo/" 
password_mgr.add_password(None, top_level_url, username, password) 
handler = urllib2.HTTPBasicAuthHandler(password_mgr) 
# 创建 "opener" (OpenerDirector 实例) 
opener = urllib2.build_opener(handler) 
# 使用 opener 获取一个URL 
opener.open(a_url) 
# 安装 opener. 
# 现在所有调用 urllib2.urlopen 将用我们的 opener.

[/codesyntax]
urllib2.install_opener(opener)
注意:以上的例子我们仅仅提供我们的HHTPBasicAuthHandler给build_opener。默认的openers有正常状况的handlers–ProxyHandler,UnknownHandler,HTTPHandler,HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor。
top_level_url 实际上可以是完整URL(包含”http:”,以及主机名及可选的端口号)例如:http://example.com/,也可以是一个“authority”(即主机名和可选的
包含端口号)例如:“example.com” or “example.com:8080”(后者包含了端口号)。权限验证,如果递交的话不能包含”用户信息”部分,例如:
“joe@password:example.com”是错误的。
Proxies代理urllib 将自动监测你的代理设置并使用他们。这个通过ProxyHandler这个在正常处理器链中的对象来处理。通常,那工作的很好。但有时不起作用
。其中一个方法便是安装我们自己的代理处理器ProxyHandler,并不定义代理。这个跟使用Basic Authentication 处理器很相似。
[codesyntax lang=”python”]

>>> proxy_support = urllib.request.ProxyHandler({}) 
>>> opener = urllib.request.build_opener(proxy_support) 
>>> urllib.request.install_opener(opener)

[/codesyntax]
注意:
此时urllib.request不支持通过代理获取https地址。但,这个可以通过扩展urllib.request达到目的。
Sockets and Layers
Python支持获取网络资源是分层结构。urllib 使用http.client库,再调用socket库实现。
在Python2.3你可以指定socket的等待回应超时时间。这个在需要获取网页的应用程序里很有用。默认的socket模型没有超时和挂起。现在,socket超时没有暴露 www.2cto.com
给http.client或者urllib.request层。但你可以给所有的sockets设置全局的超时。

Python IDLE快捷键使用

最近由于需要进行Python脚本 如果将至运行在cmd下时 总显示乱码  没办法只能想起他办法来进行解决了

想着安装Windows版本的Python的时候 默认的安装了IDLE文本编辑器  且其支持各类Windows编码  所以就优先使用这玩意了

毕竟 如果每次都用Eclipse老打开脚本 速度会很慢~~

 

但是 这样做 也有一个弊端 就是快捷键没有Eclipse那么好用了

好了  为提升速度 赶紧上网找一下IDLE的快捷键 以供与大家分享……

Ctrl + Space

完成类、方法、变量名称的自动输入,这个快捷键是我最经常使用的快捷键了,它可以完成类、方法、变量名称的自动录入,很方便.(不过在我的电脑上和输入法冲突)

Ctrl + N

快速跳转到执行的类。

Ctrl + Shift + N

跳转到指定的文件

Ctrl+Shift+Alt+N

可以快速打开符号

Ctrl + B (ctrl+点击)

跳转到定义处

Ctrl + Alt + B

跳转到方法实现处

Ctrl + Alt + T

用*来围绕选中的代码行( * 包括if、while、try catch等)这个功能也很方便,

Ctrl + W

按一个word来进行选择操作在IDEA里的这个快捷键功能是先选择光标所在字符处的单词,然后是选择源

代码的扩展区域。举例来说,对下边这个语句java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(“yyyy-MM-dd HH:mm”);当光标的位置在双引号内的字符串中时,会先选中这个字符串,然后是等号右边的表达式,再是整个句子。我一般都是在对代码进行重新修改的时候使用

它来选择出那些长长的复合表达式,很方便:)

Ctrl + Q

在editor window中显示java docs这个功能很方便–因为有时仅仅是忘记了自己编写的方法中的某个参数的含义,此时又不想再起一个浏览器来查看java doc,此时这个功能的好处就体现出来了

Alt+Q

可以不需要移动代码就能查看当前方法地声明。连续按两次会显示当前所编辑的类名

Ctrl+P

可以显示参数信息

Ctrl + /

注释/反注释指定的语句,它可以注释和反注释你所选择的语句(使用单行注释符号”//”)

Ctrl + Shift + /

用来进行多行语句的注释(即使用多行注释符号”/* … */”)

F2/Shift + F2

跳转到下/上一个错误语句、警告处IDEA提供了一个在错误语句之间方便的跳转的功能,你使用这个快捷键可以快捷在出错的语句之间进行跳转。

Shift + F6

提供对方法、变量,类,文件的重命名

Ctrl + Alt + L

根据模板格式化选择的代码,根据模板中设定的格式来format你的java代码,不过可惜的是只对java文件有效

Ctrl + Alt + I

将选中的代码进行自动缩进编排这个功能在编辑jsp文件的时候也可以工作,提供了一个对上边格式化代码功能的补充。

Ctrl + Alt + O

优化import自动去除无用的import语句。

Ctrl + ]/[

跳转到代码块结束/开始处

Ctrl+E

可以显示最近编辑的文件列表

Shift+Click

可以关闭文件。但是得点击标签栏

Ctrl+Shift+Backspace

可以跳转到上次编辑的地方

Ctrl+F12

可以显示当前文件的结构,大纲

Ctrl+F7

可以查询当前元素在当前文件中的引用,然后按F3可以选择

Alt+Insert

可以生成构造器/Getter/Setter等代码

Ctrl+Alt+V

可以引入变量。例如把括号内的SQL赋成一个变量,我非常喜欢这个功能

Alt+Up and Alt+Down

可在方法间快速移动

Alt+Enter

可以得到一些Intention Action,例如将”==”改为”equals()”

Ctrl+Shift+Space

在很多时候都能够给出Smart提示

Ctrl+Alt+Space

是类名自动完成

Alt+F3 (Ctrl+F)

可以快速寻找

Ctrl+O

可以选择父类的方法进行重写

Ctrl-I

可以选择父接口的方法进行实现

Ctrl+J

Live Templates!

Ctrl-H

要看一个所选择的类的继承层次,按Ctrl-H(Browse Type Hierarchy)即可。也可以激活编辑器中的继承关系视图查看当前编辑类的继承关系。

Ctrl+Shift+F7

可以高亮当前元素在当前文件中的使用

Alt+F7

查找当前元素在工程中的引用

Alt+F8

debug的时候计算变量值

Ctrl+Alt+Up /Ctrl+Alt+Down

可以快速跳转搜索结果

Ctrl+Shift+J

可以整合两行

Ctrl+D

复制上一行或复制选定

Ctrl+Alt+L

格式化代码

Alt+Shift+Insert

列编辑

Ctrl-Shift-V

将最近使用的剪贴板内容选择插入到文本。使用时系统会弹出一个含有剪贴内容的对话框,从中你可以选择你要粘贴的部分。

技巧篇

使用Refactor|Copy Class…可以创建一个所选择的类的“副本”。这一点很有用,比如,在你想要创建一个大部分内容都和已存在类相同的类时。

在任何工具窗口里使用Escape键都可以把焦点移到编辑器上。

Shift-Escape不仅可以把焦点移到编辑器上而且还可以隐藏当前(或最后活动的)工具窗口。

F12键把焦点从编辑器移到最近使用的工具窗口。

使用Ctrl-Shift-F7(Search | Highlight Usages in File)可以快速高亮显示当前文件中某一变量的使用地方。按Escape清除高亮显示。

Ctrl-Shift-J快捷键把两行合成一行并把不必要的空格去掉以匹配你的代码格式。

要在任何视图(Project View工程视图,Structure View结构视图或者其它视图)里快速选择当前编辑地部分(类,文件,方法或者字段),按Alt-F1(View | Select in…)。

所有视图里都提供了速查功能:在树里只需键入字符就可以快速定位到一个条目。

Python读取Jason

今天在观察python脚本的时候,看到了python解析jason数据这么一段。
经过相关查找,终于弄清楚了python是怎么解析jason结构,取得数据的。
我们通过以下命令:

[codesyntax lang=”python”]

target = urlopen(url, 'utf8')
try:
    target = json.loads(target)
except:
    print 'load json error!!'

[/codesyntax]

取得了这么一段jason数据:

[codesyntax lang=”jason”]

{
    "title": "报表",
    "tables": {
        "example1": {
            "id": "first",
            "values": [
                {
                    "key": "one",
                    "value": "1234"
                },
                {
                    "key": "two",
                    "value": "12345"
                },
                {
                    "key": "three",
                    "value": "123456"
                },
            ]
        },
        "example2": {
            "id": "second",
            "values": [
                {
                    "key": "four",
                    "value": "321"
                },
                {
                    "key": "five",
                    "value": "4321"
                },
        },
    }
}

[/codesyntax]

我们应该如何拿到里面的数据呢?比如说拿到key为“three”,value为“123456”的值,那么我们可以这样获取数据: [codesyntax lang=”python”]

get_value = target['tables']['example1']['values'][2]['value']

[/codesyntax]

首先,需要理解jason的结构:

写道

JSON建构于两种结构:
“名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

写道

JSON具有以下这些形式:
对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。

值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。

而python会把对应的jason结构翻译过来,对应的关系如下:

所以我们使用 get_value = target[‘tables’][‘example1’][‘values’][2][‘value’] 就可以得到“123456”这个值。同理,使用 get_value = target[‘tables’][‘example2’][‘values’][0][‘key’]就可以得到“four”这个值了。

JSON Python
object dict
array list
string unicode
number (int) int, long
number (real) float
true True
false False
null None  

编程武器

对程序员来说,编程语言就是武器,但有的武器好用,有的武器不好用,有的武器甚至会杀了自己

m1.png

  C语言是M1式加兰德步枪,很老但可靠。 

numchucks.png

  C++是双截棍,挥舞起来很强悍,很吸引人,但需要你多年的磨练来掌握,很多人希望改用别的武器。

molotov.png

  Perl语言是燃烧弹,曾经在战场上很有用,但现在很少人使用它。

240G.png

  Java是M240通用弹夹式自动机枪,有时它的弹夹是圆的,但有时候不是,如果不是,当你开火时,会遇到NullPointerException问题,枪就会爆炸,你被炸死。

manual.png

  Scala是M240通用机枪的变种,但它的使用手册是用一种看不懂的方言写的,很多人怀疑那只是一些梦话。

sword.png

  JavaScript是一把宝剑,但没有剑柄。

starterpistol.png

  Go语言是一种自制的“if err != nil”发令枪,每一次发射后,你都必须要检查它是否真的发射了。

3dprintedgun.png

  Rust语言是一种3D打印出的枪。将来也许真的能派上用场。

hammer.png

  bash是一个十分碍手的锤子,你抡起它时会发现所有东西看起来都像钉子,尤其是你的指头。

doublebarrel.png

  Python是一种“v2/v3”双管枪,每次只能用一个管子发射,你永远不知道该用哪个管子发射好。

rubysword.png

  Ruby是一把外嵌红宝石的宝刀,人们使用它通常是因为看起来很炫。

hose.png

  PHP是水管子,你通常会把它的一段接到汽车的排气管,另一端插进车窗里,然后你坐进车里,开动引擎。

spaceweapon.png

  Mathematica是一种地球低轨道粒子大炮,它也许能够干出很神奇的事情,但只有付得起费用的人才能使用它。

donkeylaser.png

  C#是一种强悍的激光大炮,架子一头驴子上,如果从驴子上卸下来,它好像就发不出激光。

ai.png

  Prolog语言是一种人工智能武器,你告诉它要做什么,它会照做不误,但之后,它会弄几个终结者出来,烧掉你的房子。

shiv.png

  Lisp语言是一把剃须刀,有很多款式。只有寻求刺激和危险的人才会使用它。

  via:techug

Python字符串查找

python 字符串查找有4个方法,1 find,2 index方法,3 rfind方法,4 rindex方法。

1 find()方法:查找子字符串,若找到返回从0开始的下标值,若找不到返回-1[codesyntax lang=”python”]

info = 'abca'
print info.find('a')##从下标0开始,查找在字符串里第一个出现的子串,返回结果:0

info = 'abca'
print info.find('a',1)##从下标1开始,查找在字符串里第一个出现的子串:返回结果3

info = 'abca'
print info.find('333')##返回-1,查找不到返回-1
[/codesyntax ]

2 index()方法:

python 的index方法是在字符串里查找子串第一次出现的位置,类似字符串的find方法,不过比find方法更好的是,如果查找不到子串,会抛出异常,而不是返回-1[codesyntax lang="python"]

info = 'abca'
print info.index('a')
print info.index('33')
[/codesyntax ]

rfind和rindex方法用法和上面一样,只是从字符串的末尾开始查找。

14个程序员常逛的开发社区

作为程序员,选择好合适的开发社区对提高自己的编程能力会有很大的帮助,我也说不出为什么,但是一些优秀的实时开发社区确实能帮你积累不少开发经验。

下面这张图列出了14个程序员经常逛的顶级开发社区,作为程序员,你应该要了解其中一个或者最好是多个,并且学会使用它们,利用里面的资源提高自己的编程能力。

我们期望在开发者社区中获得什么?

我们希望能得到切实的帮助,而不是获取一些唠叨的废话或者一些水文。我们希望能根据自己提出的问题来获得其他开发者的回答帮助或者讨论一些学习资源的问题。下图是一些开发者在社区中最关注的一些问题。

下面我们来看一下程序员经常去的14个顶级开发者社区,如果你还不知道它们,那么赶紧去看看,也许会有意想不到的收获。

 Stack Overflow

9月份,Stack Overflow也将迎来其6岁的生日,毫无疑问,Stack Overflow是全球最受程序员欢迎的开发社区,而且也是内容最丰富的社区之一。

官方网站:http://stackoverflow.com/

 Reddit

reddit也是一个非常富有个性的社区,你可以在reddit上提交一些感兴趣的话题,也可以和其他程序员讨论一些编程开发的问题和当前的IT热点资讯,reddit是一个用户粘性比较强的开放社区,编程开发板块只是其中的一小部分。

官方网站:http://www.reddit.com/r/programming

 Google+ Communities

加入Google+社区只需要一个Google账户即可,你可以完全免费的获取里面的资源。

官方网站:https://plus.google.com/communities

 SitePoint

SitePoint社区论坛也是我最喜欢的在线开发社区和程序员设计师家园之一,SitePoint主要目标是帮助初学者了解其选择的编程语言和技术,并且得到相应的提高,网站内容包括web开发、web设计、技术写作以及用户体验等。

官方网站:http://www.sitepoint.com/forums/

 CodeProject

截止2013年8月,已经有100多万用户入驻codeproject,并且分享了约100多万个代码演示,在codeproject里,你可以将代码分享给你的朋友们。和其他社区不同的是,codeproject更加侧重软件开发,比如C, C#, C++, Java, Lisp等开发。

官方网站:http://www.codeproject.com/

 Treehouse

在寻找一个实惠的编程学习途径吗?你可以试试加入treehouse,它并不昂贵,年度会员还可以打折优惠。treehouse非常简单,你可以在上面找到各种等级的问题答案。

官方网站:https://teamtreehouse.com/forum

 Hacker News

Hacker News这个名字已经刻在很多开发者心里了,在这里,可以实时看到编程界中发生的任何事情,包括一些学习的资源和教程。你可以从用户提交的数据中找到适合你的学习资源,比如文章、图像视频以及一些问题的讨论。

官方网站:https://news.ycombinator.com/news

 DZone

DZone是一个允许用户分享最新IT新闻和编程资源的社区,这是一个文章内容驱动的社区,所以需要许多内容管理员来把关文章的质量,从某种意义上说,它与HN和其他的编程社区类似,但是这个平台时间最长,里面的用户数量也是最多的。

官方网站:http://www.dzone.com/links/index.html

 Bytes

Bytes是一个传统的开发社区,新手和专家都可以在里面讨论一些关于软件开发、数据库开发以及网络和系统管理的问题。数据库、网络以及系统是编程的基础,我们需要关注这方面的问题,从而能更好的帮助我们提高编程能力。

官方网站:http://bytes.com/

 DaniWeb

DaniWeb以前是专为市场营销业务分析人员设计的,但是现在主要为各个年龄段的Web开发者和程序员服务。

官方网站:http://www.daniweb.com/

 Dream In Code

这几年,它的更新比较缓慢了,这有好的一面也有坏的一面,60w的用户以及百万及的文章,内容涵盖 Java, C++, VB.NET等,学习资源相当丰富。

官方网站:http://www.dreamincode.net/forums/

 Tech.Pro

Tech.pro是一个关注科技领域发展的相关资讯的社区,Tech.pro是一个获取资源和教程的入门网站,包含一些技术教程、讨论、博客已经链接等。

官方网站:http://tech.pro/

 Pineapple

也许这还算不上活跃的优秀开发社区,但是这里也包含很多有用的工具、教程以及类库资源等。我在几个月前开始使用Pineapple,现在已经比较依赖它了。

官方网站:http://pineapple.io/

 Lobsters

这是一个用户邀请制的开发社区,是一个真正“面向社交”的社区,你可以在里面找到大量的关于编程的任何讨论,很多信息都至少有20多条回帖,这些信息或许对你会有很大帮助。

官方网站:https://lobste.rs/

常见设计模式面试问题

不管是参加Java面试还是C#面试,设计模式软件设计都是任何编程面试中的必问问题。实际上,编程能力和设计技巧是对彼此很好的补充。一个好的程序员通常都是一个好的软件设计人员。他们知道怎么把一个问题分割成一段段代码或者软件设计,但这些能力和技巧并不能凭空而来。你需要持续做大型、小型系统的设计和编码,并且不断从错误中学习。从面向对象设计原则 开始是一个不错的选择。好吧,这篇文章是关于一些在各种面试中频繁问到的一些设计问题。考虑到针对性和困难度,我把它们分成两个种类,分别针对初学者和有经验的人。

 对中高级别的设计模式面试问题

这是一些和设计模式还有软件设计都相关的问题。这些问题需要一些思考和经验来回答。在大多数情况下,面试官并不是需要一个确切的答案,而是希望听到你的想法,你对这个问题是怎么考虑的,你能不能想通这个问题,能不能挖掘一些没有告诉你的潜在信息。在解决一个问题时你应该考虑什么等等可以使你经验大涨。总的来说,这些设计问题会让你动起脑来。有时面试官也会让你写代码,所以还是准备一下吧。如果你知道编程和设计技巧中的概念,例子和程序,你应该可以在这些问题中有突出的表现。

1. 举出一个例子,在这种情况你会更倾向于使用抽象类,而不是接口?

这是很常用但又是很难回答的设计面试问题。接口和抽象类都遵循”面向接口而不是实现编码”设计原则,它可以增加代码的灵活性,可以适应不断变化的需求。下面有几个点可以帮助你回答这个问题:

  1. 在Java中,你只能继承一个类,但可以实现多个接口。所以一旦你继承了一个类,你就失去了继承其他类的机会了。
  2. 接口通常被用来表示附属描述或行为如:Runnable、Clonable、Serializable等等,因此当你使用抽象类来表示行为时,你的类就不能同时是Runnable和Clonable(译者注:这里的意思是指如果把Runnable等实现为抽象类的情况),因为在Java中你不能继承两个类,但当你使用接口时,你的类就可以同时拥有多个不同的行为。
  3. 在一些对时间要求比较高的应用中,倾向于使用抽象类,它会比接口稍快一点。
  4. 如果希望把一系列行为都规范在类继承层次内,并且可以更好地在同一个地方进行编码,那么抽象类是一个更好的选择。有时,接口和抽象类可以一起使用,接口中定义函数,而在抽象类中定义默认的实现。

希望了解更多关于Java接口的,可以看我的文章Java接口需要知道的10件事。

2. 设计一个贩卖机,可以接收不同的货币,出售不同的产品?

这是一个开放设计问题,你可以作为练习,尝试着写出设计文档、代码和JUnit测试而不是只是解决这个问题,看看它花了你多少时间得到解决方案和得到需要的原形。理想情况下,这个问题应该可以在3个小时内解决,至少应该得到一个可以运行的版本。

3. 你有一个Smartphone类,可以派生如IPhone、AndroidPhone、WindowsMobilePhone类

它还可以是一些有着品牌的手机名称,你会怎么设计这个类系统呢。

这是另外一个设计模式练习,你可以应用你的面向对象设计技巧来得到一个设计,这个设计需要足够灵活能够支持未来产品的扩展,足够稳定能够支持在现有模型进行修改。

4. 在Java中,什么时候用重载,什么时候用重写?

对有经验的Java设计师来说,这是一个相当简单的问题。如果你看到一个类的不同实现有着不同的方式来做同一件事,那么就应该用重写(overriding),而重载(overloading)是用不同的输入做同一件事。在Java中,重载的方法签名不同,而重写并不是。

5. 设计一个ATM机?

我们所有人都使用ATM(自动柜员机)。想想你会怎么设计一个ATM?就设计金融系统来说,必须知道它们应该在任何情况下都能够如期工作。不管是断电还是其他情况,ATM应该保持 正确的状态(事务) , 想想 加锁(locking)、事务(transaction)、错误条件(error condition)、边界条件(boundary condition) 等等。尽管你不能想到具体的设计,但如果你可以指出非功能性需求,提出一些问题,想到关于边界条件,这些都会是很好的一步。

6. 你正在写一些类提供市场数据,你知道你可以不定时切换不同的厂商如Reuters、wombat或者直接的批发商, 你会如何设计你的市场数据系统。

这是一个非常有趣的设计面试问题,并且真的在一家大的投资银行问到过,如果你是用Java编码的话这是一个相当平常的场景。最主要的一点是你要有一个MarketData接口,它会有调用端需要的方法如:getBid()、getPrice()、getLevel()等等,而MarketData应该由一个MarketDataProvider通过 依赖注入(dependency injection) 组成。因此,当你修改你的MarketData 提供器(MarketDataProvider)时,调用端不会受影响,因为它们是通过MarketData接口或类的方法来访问的。

7. 在Java中,为什么不允许从静态方法中访问非静态变量?

你在Java中不能从静态上下文访问非静态数据只是因为非静态变量是跟具体的对象实例关联的,而静态的却没有和任何实例关联。你可以看我的文章为什么在静态上下文中不能访问非静态变量查看详细的讨论。

8. 在Java中设计一个并发规则的pipeline?

并发编程或并发设计这些天很火,它可以充分利用现在不断提升的高级处理器的处理能力,而Java成为一个多线程语言也从这种情况获益良多。设计一个并发系统需要记住的最关键的点是线程安全,不可变性,本地变量和避免使用static或者类变量(instance variables)。你只需要想着每一类都可以同时被多个线程同时执行,所以最好的做法就是每一个线程都处理自己的数据 ,不跟其他数据交互,并且运行时只需要最小的同步保证。这个问题可以涉及到从最初的讨论到完整的类和接口编码,但只要你记住并发中最重要的点和问题如,竞争条件(race condition)、死锁(deadlock)、内存交互问题(memory interference)、原子性、ThreadLocal变量等,你都可以回答它。

  给初学者的设计模式面试问题

这些软件设计和设计模式问题大多在初学者层次时被问起,目的只是了解一下候选人(应聘者)对设计模式知道多少,如, 设计模式是什么 或者 一个特定的设计模式做什么 ?这些问题通过简单地记忆概念就可以回答,但就信息和知识而言还是有价值的。

1. 什么是设计模式?你是否在你的代码里面使用过任何设计模式?

设计模式是世界上各种各样程序员用来解决特定设计问题的尝试和测试的方法。设计模式是代码可用性的延伸。

2. 你可以说出几个在JDK库中使用的设计模式吗?

装饰器设计模式(Decorator design pattern)被用于多个Java IO类中。单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如Boolean,像Boolean.valueOf,观察者模式(Observer pattern)被用于Swing和很多的事件监听中。

3. Java中什么是单例设计模式?用Java写出线程安全的单例

单例模式重点在于在整个系统上共享一些创建时较耗资源的对象。整个应用中只维护一个特定类实例,它被所有组件共同使用。Java.lang.Runtime是单例模式的经典例子。你可以在我的文章Java单例模式的10个问题看到更多的问题和讨论。从Java 5开始你可以使用枚举(enum)来实现线程安全的单例。

4. 使用工厂模式最主要的好处是什么?你在哪里使用?

工厂模式的最大好处是增加了创建对象时的封装层次。如果 你使用工厂来创建对象,之后你可以使用更高级和更高性能的实现来替换原始的产品实现或类,这不需要在调用层做任何修改。可以看我的文章工厂模式得更详细的解释和和了解更多的好处。

5. 在Java中,什么叫观察者设计模式(observer design pattern)?

观察者模式是基于对象的状态变化和观察者的通讯,以便他们作出相应的操作。简单的例子就是一个天气系统,当天气变化时必须在展示给公众的视图中进行反映。这个视图对象是一个主体,而不同的视图是观察者。可以在这篇文章中看到Java观察者模式的完整例子。

6. 举一个用Java实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?

装饰模式增加强了单个对象的能力。Java IO到处都使用了装饰模式,经典的例子就是Buffered系列类如BufferedReader和BufferedWriter,它们增强了Reader和Writer对象,以实现提升性能的Buffer层次的读取和写入。可以看这篇文章了解更多。

7. 什么是MVC设计模式?举一个MVC设计模式的例子?

8, Java中什么是表示层设计模式(FrontController design pattern)?举一个使用表示层设计模式(front controller pattern)的例子?

9. 什么是责任链模式(Chain of Responsibility)?

10. 什么是适配器模式?举用Java实现适配器模式的例子?

这些留给你自己做练习,作为面试准备,试着去找出这些设计模式的答案。

这些是我在很多面试中都看到的设计模式问题,当然,在google面试和各种各样的公司如Amzone、Microsoft等等还有很多重要的专业软件设计问题。如果你遇到一些有趣的值得分享的设计问题,不妨分享出来。