python 字典的一些操作

字典是一个非常常用的数据类型,这一篇记录一些常用用法。

遍历

dict={"a":"apple","b":"banana","o":"orange"} 

for i in dict: 
  print "dict[%s]=" % i,dict[i] 

for (k,v) in  dict.items(): 
  print "dict[%s]=" % k,v 

for k,v in dict.iteritems(): 
  print "dict[%s]=" % k,v 

for k,v in zip(dict.iterkeys(),dict.itervalues()): 
  print "dict[%s]=" % k,v

key 是否存在

dict.has_key()
key in dict.keys()

for 循环按顺序输出

字典的本质是hash表,一种散列表结构,数据输入后按特征已经被散列了,注定它就是无序的。

所以预先添加的内容输出的顺序是不可预期的。有两种解决方法

  1. 不使用dict,使用元组,元组是记录输入顺序的、有序的,也能方便地转换成dict。
  2. 另用一个列表记录下输入时的顺序。

参考资料


Python Selenium 的 XPath 定位方式详解

先介绍一下 XPath。XPath 是一门在 XML 文档中查找信息的语言。可用来在 XML 文档中对元素和属性进行遍历。

在 selenium 中定位元素,使用 XPath 能更好的抽象代码(比如讲 XPath 表达式提取成一个单独的配置)。所以我在日常使用中尽量使用 XPath。

HTML与XML

html 是标记语言,XML 是标记语言的元语言。

HTML和XML的最大区别在于:HTML是一个定型的标记语言,它用固有的标记来描述,显示网页内容。比如<H1>表示首行标题,有固定的尺寸。相对的,XML则没有固定的标记,XML不能描述网页具体的外观,内容,它只是描述内容的数据形式和结构。

Xpath定位方法

本小节节选自 Xpath定位方法深入探讨及元素定位失败常见情况

绝对定位

driver.findElement(By.xpath("/html/body/div/form/input"))。

特点:这个路径是从网页起始标签开始一直到要定位的元素的路径,如果要定位的元素在页面最下面,则这个Xpath路径会非常长。如果在要定位的元素与页面开始之间的元素有任何增减,元素定位就会失败。

相对定位

driver. findElement(By.xpath ("//input") )

返回查找到的第一个符合条件的元素。

特点:相对路径一般只会包含与被定位元素最近的几层元素有关,相对路径写的好的话,页面变动影响最小,而且定位准确。

索引定位

使用索引定位元素,索引的初始值为1。

driver. findElement(By.xpath ("//input[2]") )

返回查找到的第二个符合条件的元素。

属性值定位

driver. findElement(By.xpath ("//input[@id='username']"));
driver. findElement(By.xpath ("//img[@alt='flowr']"));

特点:属性定位也是比较常用的方法,如果元素中没有常见的id,name,class等直接有方法可调用的属性,也可以查找元素中是否有其他能唯一标识元素的属性,如果有,就可以用此方法定位。

逻辑运算符 and与or

driver.findElement(By.xpath("//input[@id='username' and @name='userID']"));

特点:多个属性值联合定位,更能准确定位到元素。并且如果多个相同标签的元素,如果其包含的属性值有不同的,也可以用这个方法区分开来。

属性名定位

driver. findElement(By.xpath ("//input[@button]"))

特点:此方法可以区分同一种标签,含有不同属性名的元素。定位相对简单一些儿,但也同样存在着无法区分同种标签含有同种属性名的多个元素,这个时候要配合索引定位才行。

属性值匹配

(a)starts-with()

driver. findElement(By.xpath ("//input[stars-with(@id,'user')]"))

(b)ends-with()

driver. findElement(By.xpath ("//input[ends-with(@id,'name')]"))

(c)contains()

driver. findElement(By.xpath ("//input[contains(@id,"ernam")]"))

特点:此方法更加灵活,可以定位属性值不太规律,或是部分变动,中间有空格的情况。注:如果属性值中间包含空格,Webdriver定位的时候容易出错,时而能定位到时而定位不到,所以应该避免用含用空格的属性值定位。可以采用此方法,进行部分属性值定位。

任意属性值匹配

driver. findElement(By.xpath ("//input[@*='username']"))

特点:此方法相当于模糊查询,只要欲定位的标签,如input中任何属性值等于‘username’,就能匹配成功。缺点,可能会匹配含有这个属性值的其他元素,所以我们在定位的时候要查看一下这个元素值在页面中是否唯一。

XPath 轴匹配

选自 Python selenium —— 父子、兄弟、相邻节点定位方式详解

普通方式
# -*- coding: utf-8 -*-
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('http://www.baidu.com')

# 1.xpath 父子关系
print driver.find_element_by_xpath("//div[@id='B']/div").text

# 1.xpath 父子关系
# `.`代表当前节点; '..'代表父节点
print driver.find_element_by_xpath("//div[@id='C']/../..").text

# 1.xpath,通过父节点获取其哥哥节点
print driver.find_element_by_xpath("//div[@id='D']/../div[1]").text

# 1.xpath,通过父节点获取其弟弟节点
print driver.find_element_by_xpath("//div[@id='D']/../div[3]").text
XPath 轴
# 1.xpath轴 child 父子关系
print driver.find_element_by_xpath("//div[@id='B']/child::div").text # child是xpath默认的轴,可以忽略不写

# 1.xpath轴 parent 父子关系
print driver.find_element_by_xpath("//div[@id='C']/parent::*/parent::div").text

# 1.xpath轴 preceding-sibling 哥哥节点
print driver.find_element_by_xpath("//div[@id='D']/preceding-sibling::div[1]").text

# 1.xpath轴 following-sibling 弟弟节点
print driver.find_element_by_xpath("//div[@id='D']/following-sibling::div[1]").text

# 1.xpath轴 following 弟弟节点
print driver.find_element_by_xpath("//div[@id='D']/following::*").text

xpath常用函数

  1. child 选取当前节点的所有子节点
  2. parent 选取当前节点的父节点
  3. descendant 选取当前节点的所有后代节点
  4. ancestor 选取当前节点的所有先辈节点
  5. descendant-or-self 选取当前节点的所有后代节点及当前节点本身
  6. ancestor-or-self 选取当前节点所有先辈节点及当前节点本身
  7. preceding-sibling 选取当前节点之前的所有同级节点
  8. following-sibling 选取当前节点之后的所有同级节点
  9. preceding 选取当前节点的开始标签之前的所有节点
  10. following 选去当前节点的开始标签之后的所有节点
  11. self 选取当前节点
  12. attribute 选取当前节点的所有属性
  13. namespace 选取当前节点的所有命名空间节点

路径表达式

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 匹配任意多的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=’eng’] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

通配符

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述  
* 匹配任何元素节点。  
@* 匹配任何属性节点。  
node() 匹配任何类型的节点。

例子:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。

多个表达式

通过在路径表达式中使用“|”运算符,您可以选取若干个路径 例子:

路径表达式 结果  
//book/title //book/price 选取 book 元素的所有 title 和 price 元素。
//title //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

关键字

关键字 结果
starts-with 顾名思义,匹配一个属性开始位置的关键字
contains 匹配一个属性值中包含的字符串
text() 匹配的是显示文本信息,此处也可以用来做定位用
Sibling 提取指定元素的所有同级元素,即获取目标元素的所有兄弟节点。

例子:

例子 结果
//input[starts-with(@name,’name1’)] 查找name属性中开始位置包含’name1’关键字的页面元素
//input[contains(@name,’na’)] 查找name属性中包含na关键字的页面元素
//a[text()=’百度搜索’]  
//a[contains(text(),”百度搜索”)]  
//a[not(contains(@id, ‘xx’))]  
//div[(contains(@class,’typeA’) or contains(@class,’typeB’)) and not(contains(@class,’ng-hide’))]  

参考资料


Python 的 object 类

结论

先说结论,Python中的一切都是对象,它们要么是类的实例,要么是元类的实例 .

在图中可以看出对象分两种:

  1. classes(类)
  2. instances(实例)

虚线表示一个对象的type(类型),实线表示一个对象的base(基类/父类).

首先我们要明确,类创造了实例,而不是继承关系。那么问题来了,是什么创造了类呢? Python 引进了metaclasses,<type 'type'>就是元类,它可以创建类.

使用

可以参考一下这些链接:

由于历史原因,2.x 里 object 是新基类,需要显示定义。在3.x里,object已经默认做为所有东西的基类了。

class A:  # 旧式类
    pass

class B(object):  # 新式类
    pass

两个方法:

  • issubclass(A,B) (测试超类-子类关系) :A 是 B 的子类,B 是 A 的超类
  • isinstance(A,B) (测试类型-实例关系) ,A 是 B 的实例

    class Foo(object):
        pass
    	
    class Bar(Foo):
        pass
    	
    print issubclass(Foo,object)
    print issubclass(Bar,object)
    print isinstance(Bar(),Foo)
    

原因

那么问题来了,为什么要加入新式类呢?

新式类有很多优势:

  • 基于内建类型构建新的用户类型
  • 支持property和描述符特性等.
  • 定义了一些特殊方法,子类可以对这些方法进行覆盖以满足自身的特殊需求.

      `__new__()`
      `__init__()`
      `__delattr__()`
      `__getattribute__()`
      `__setattr__()`
      `__hash__()`
      `__repr__()`
      `__str__()`
    

另外新式类和旧式类还有一个区别就是在多继承的时候,查找要调用的方法。新式类是广度优先的查找算法。旧式类的查找方法是深度优先的.

参考资料


Python 中的 if __name__ == '__main__'

if name == ‘main’ 是一个Python 初学者摸不着头脑的东西。例如下面一个简单的文件:

PI = 3.14

def main():
    print "PI:", PI

if __name__ == "__main__":
    main()

引用知乎上的这个非常简约的答案:

name 是当前模块名,当模块被直接运行时模块名为 main 。这句话的意思就是,当模块被直接运行时,以下代码块将被运行,当模块是被导入时,代码块不被运行。』

下面循序渐进做一些解释。

首先先普及Python 的一个基础概念——模块。

Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。
模块让你能够有逻辑地组织你的 Python 代码段。
把相关的代码分配到一个模块里能让你的代码更好用,更易懂。
模块能定义函数,类和变量,模块里也能包含可执行的代码。

所有的模块都有一个内置属性 name。一个模块的 name 的值取决于您如何应用模块。

如果 import 一个模块,那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名。但是您也可以像一个标准的程序样直接运行模块,在这 种情况下, name 的值将是一个特别缺省”main“。

解释型语言和编译型语言

首先我们平时所使用的程序语言都是高级程序语言,分为解释型语言和编译型语言。

对于编译型语言——C,C++,以及完全面向对象的编程语言 Java,C# 等,他们都是先将程序编译成二进制再运行,都需要有一个 main 函数来作为程序的入口。

而解释型语言(比如 Python)则不同,它是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。

一个 Python 源码文件除了可以被直接运行外,还可以作为模块(也就是库)被导入。不管是导入还是直接运行,最顶层的代码都会被运行(Python 用缩进来区分代码层次)。

name

__name__ 是内置变量,用于表示当前模块的名字,同时还能反映一个包的结构。

如果一个模块被直接运行,则其没有包结构,其 __name__ 值为 __main__。比如我们新建一个文件 test.py

# -*- coding:utf-8 -*-
print __name__

运行 python test.py 输出结果为

__main__

如果是以导入的方式运行的,比如我们再新建一个文件 testMain.py,仅仅导入不做任何事:

# -*- coding:utf-8 -*-
import test

运行 python testMain.py 输出结果为

test

我们也可以直接以模块的方式运行 test.py文件——python -m test.py,结果如下:

test
xxxx : No module named test.py

到这里,我们基本上就完全知道了 __name__ 是什么了。

参考资料


python 自定义一个 setting 模块并使用其变量

最简单的方式是定义一个 setting 的 module:

	(settings.py)
	
	CONSTANT1 = "value1"
	CONSTANT2 = "value2"
	
	(consumer.py)
	
	import settings
	
	print settings.CONSTANT1
	print settings.CONSTANT2

当我们引用 settings 模块里的变量时需要在前面添加模块的名称。如果我们真的不想添加模块的名称,并且我需要担心变量可能会改变,那么我们可以使用按照下面的方式引入:

	from settings import CONSTANT1, CONSTANT2
	
	print CONSTANT1
	print CONSTANT2

然而这样子其实会导致其他人阅读这个代码的时候不知道这变量从哪来的。所以最简单的方式应该是这样:

	import settings as s
	
	print s.CONSTANT1
	print s.CONSTANT2

方便了输入,又使得代码易懂。

参考资料


python 代码阅读和有趣的项目推荐

做个记录看看。

个人收集的一些好玩项目和文章

(未完待续)以下都是转载


Python之禅

个人推荐看 Kenneth Reitz 大神的成名之作 Requests,感受一下什么是真正的Pythonic代码,什么是 Keep It Simple and Stupid

有网友已经整理了一份Requests源码阅读清单,内容幽默诙谐有趣,推荐看一看

還有老外分享的一個PPT,手把手教你如何阅读源码,也是拿Requests作为参考例子 https://www.slideshare.net/onceuponatimeforever/lets-read-code ,没有梯子的在这里下载 https://pan.baidu.com/s/1i5ggKjr

下面是Kenneth Reitz大神自己推薦的源碼閱讀清單,來源:Reading Great Code

  • Howdoi Howdoi is a code search tool, written in Python
  • Flask Flask is a microframework for Python based on Werkzeug and Jinja2. It’s intended for getting started very quickly and was developed with best intentions in mind.
  • Diamond Diamond is a python daemon that collects metrics and publishes them to Graphite or other backends. It is capable of collecting cpu, memory, network, i/o, load and disk metrics. Additionally, it features an API for implementing custom collectors for gathering metrics from almost any source.
  • Werkzeug Werkzeug started as simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility modules. It includes a powerful debugger, full-featured request and response objects, HTTP utilities to handle entity tags, cache control headers, HTTP dates, cookie handling, file uploads, a powerful URL routing system and a bunch of community-contributed addon modules.
  • Requests Requests is an Apache2 Licensed HTTP library, written in Python, for human beings.
  • Tablib Tablib is a format-agnostic tabular dataset library, written in Python.

董伟明

推荐阅读我的专栏文章:教你阅读Python开源项目代码 - Python之美 - 知乎专栏。 我摘录一部分:

我个人的喜好

和工作中看别人代码差不多,基本每个人、每个项目、每个团队都有自己写代码的风格,比如变量命名风格、某些语言特性使用方式、代码规范要求、目录风格等,其实开源项目的作者也是一样。看代码,如看人(团队)。 首先介绍下我的喜好(排名分先后):

1. kennethreitz。requests和python-guide作者。他还有一个非常励志的故事,有兴趣的可以看 谁说程序员不是潜力股?

2. mitsuhiko。flask、Jinja2、werkzeug和flask-sqlalchemy作者。

3. sigmavirus24。flake8、pycodestyle(原pep8)、requests、urllib3等项目的主要贡献者和维护者。

4. ask。Celery及相关依赖的作者。

5. ajdavis。mongo-python-driver(pymongo)、tornado等项目的主要贡献者。

6. bitprophet。fabric、paramiko(Python的ssh库)作者。

前2个是公认的Python领域代码写的最好的、最有创意的工程师。

初学者推荐阅读项目

初学者可以先阅读一些代码量比较少的,最好是单文件的项目:

1. GitHub - kennethreitz/pip-pop: Tools for managing requirements files.

2. GitHub - kennethreitz/envoy: Python Subprocesses for Humans™.

3. GitHub - kennethreitz/records: SQL for Humans™

4. GitHub - mitsuhiko/pluginbase: A simple but flexible plugin system for Python.

5. GitHub - mitsuhiko/pipsi: pip script installer

6. GitHub - mitsuhiko/unp: Unpacks things.

7. GitHub - chrisallenlane/cheat

8. GitHub - jek/blinker: A fast Python in-process signal/event dispatching system.

9. GitHub - mitsuhiko/platter: A useful helper for wheel deployments.

10. GitHub - kennethreitz/tablib: Python Module for Tabular Datasets in XLS, CSV, JSON, YAML, &amp;amp;c.

看代码主要是了解别人写代码的方式,语法实践这些内容。看完之后,你可以针对这些项目能解决的问题自己写个项目,写完之后和上述项目去对比一下,看看哪些方面做的不好。

进阶阅读项目

进阶的时候就要阅读一些相对复杂的项目,它们能帮助你提升Python编程技巧:

1. faif/python-patterns。使用Python实现一些设计模式的例子。

2. pallets/werkzeug。flask的WSGI工具集。其中包含了实现非常好的LocalProxy、cached_property、import_string、find_modules、TypeConversionDict等。

3. bottlepy/bottle。阅读一个Web框架对Web开发就会有更深刻的理解,flask太大,bottle就4k多行,当然如果你有毅力和兴趣直接看flask是最好了的。

4. msiemens/tinydb。了解用Python实现数据库。

5. coleifer/peewee。了解ORM的实现。

6. pallets/click。click已经内置于在flask 0.11里,提供命令行功能,值得阅读。

7. mitsuhiko/flask-sqlalchemy。了解一个flask插件是怎么实现的。

除此之外Web开发者可以阅读一些相关的项目:

1. runscope/httpbin。使用flask,网站是httpbin(1): HTTP Client Testing Service

2. jahaja/psdash。使用flask和psutils的获取Linux系统信息的面板应用。

3. pallets/flask-website。 flask官方网站应用。

4. pypa/warehouse。如果你使用pyramid,这个新版的PYPI网站,可以帮助你理解很多。

当然,2个学习flask重要的资源必须爆一爆:

1. GitHub - realpython/discover-flask: Full Stack Web Development with Flask

2. The Flask Mega-Tutorial。 这个就是《Flask Web开发:基于Python的Web应用开发实战》的原始博客。

500lines

推荐一个非常厉害的项目 GitHub - aosabook/500lines: 500 Lines or Less, 它里面包含了22个由该领域的专家完成,用不到500行的代码实现一个特定功能的子项目。连Guido van Rossum都亲自来写基于asyncio爬虫了,Nick Coghlan、ajdavis也出场了。更具体的介绍可以看Python 的练手项目有哪些值得推荐? - 小小搬运工的回答

欢迎关注本人的微信公众号获取更多Python相关的内容(也可以直接搜索「Python之美」):

http://weixin.qq.com/r/D0zH35LE_s_Frda89xkd (二维码自动识别)

参考资料