中国领先的IT技术网站
|
|
创建专栏

Python语法速览与实战清单

人生苦短,请用 Python,大量功能强大的语法糖的同时让很多时候 Python 代码看上去有点像伪代码。譬如我们用 Python 实现的简易的快排相较于 Java 会显得很短小精悍。

作者:张梓雄|2017-11-23 15:24

开发者大赛路演 | 12月16日,技术创新,北京不见不散


本文是对于 现代 Python 开发:语法基础与工程实践的总结,更多 Python 相关资料参考 Python 学习与实践资料索引;本文参考了 Python Crash Course - Cheat Sheets,pysheeet 等。本文仅包含笔者在日常工作中经常使用的,并且认为较为关键的知识点与语法,如果想要进一步学习 Python 相关内容或者对于机器学习与数据挖掘方向感兴趣,可以参考程序猿的数据科学与机器学习实战手册

基础语法

Python 是一门高阶、动态类型的多范式编程语言;定义 Python 文件的时候我们往往会先声明文件编码方式:

  1. # 指定脚本调用方式 
  2. #!/usr/bin/env python 
  3. # 配置 utf-8 编码 
  4. # -*- coding: utf-8 -*- 
  5.  
  6. # 配置其他编码 
  7. # -*- coding: <encoding-name> -*- 
  8.  
  9. # Vim 中还可以使用如下方式 
  10. # vim:fileencoding=<encoding-name

人生苦短,请用 Python,大量功能强大的语法糖的同时让很多时候 Python 代码看上去有点像伪代码。譬如我们用 Python 实现的简易的快排相较于 Java 会显得很短小精悍:

  1. def quicksort(arr): 
  2.     if len(arr) <= 1: 
  3.         return arr 
  4.     pivot = arr[len(arr) / 2] 
  5.     left = [x for x in arr if x < pivot] 
  6.     middle = [x for x in arr if x == pivot] 
  7.     right = [x for x in arr if x > pivot] 
  8.     return quicksort(left) + middle + quicksort(right
  9.      
  10. print quicksort([3,6,8,10,1,2,1]) 
  11. # Prints "[1, 1, 2, 3, 6, 8, 10]" 

控制台交互

可以根据 __name__ 关键字来判断是否是直接使用 python 命令执行某个脚本,还是外部引用;Google 开源的 fire 也是不错的快速将某个类封装为命令行工具的框架:

  1. import fire 
  2.  
  3. class Calculator(object): 
  4.   """A simple calculator class.""" 
  5.  
  6.   def double(self, number): 
  7.     return 2 * number 
  8.  
  9. if __name__ == '__main__'
  10.   fire.Fire(Calculator) 
  11.  
  12. # python calculator.py double 10  # 20 
  13. # python calculator.py double --number=15  # 30 

Python 2 中 print 是表达式,而 Python 3 中 print 是函数;如果希望在 Python 2 中将 print 以函数方式使用,则需要自定义引入:

  1. from __future__ import print_function 

我们也可以使用 pprint 来美化控制台输出内容:

  1. import pprint 
  2.  
  3. stuff = ['spam''eggs''lumberjack''knights''ni'
  4. pprint.pprint(stuff) 
  5.  
  6. # 自定义参数 
  7. pp = pprint.PrettyPrinter(depth=6) 
  8. tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead',('parrot', ('fresh fruit',)))))))) 
  9. pp.pprint(tup) 

模块

Python 中的模块(Module)即是 Python 源码文件,其可以导出类、函数与全局变量;当我们从某个模块导入变量时,函数名往往就是命名空间(Namespace)。而 Python 中的包(Package)则是模块的文件夹,往往由 __init__.py 指明某个文件夹为包:

  1. # 文件目录 
  2. someDir/ 
  3.     main.py 
  4.     siblingModule.py 
  5.  
  6. # siblingModule.py 
  7.  
  8. def siblingModuleFun(): 
  9.     print('Hello from siblingModuleFun'
  10.      
  11. def siblingModuleFunTwo(): 
  12.     print('Hello from siblingModuleFunTwo'
  13.  
  14. import siblingModule 
  15. import siblingModule as sibMod 
  16.  
  17. sibMod.siblingModuleFun() 
  18.  
  19. from siblingModule import siblingModuleFun 
  20. siblingModuleFun() 
  21.  
  22. try: 
  23.     # Import 'someModuleA' that is only available in Windows 
  24.     import someModuleA 
  25. except ImportError: 
  26.     try: 
  27.         # Import 'someModuleB' that is only available in Linux 
  28.         import someModuleB 
  29.     except ImportError: 

Package 可以为某个目录下所有的文件设置统一入口:

  1. someDir/ 
  2.     main.py 
  3.     subModules/ 
  4.         __init__.py 
  5.         subA.py 
  6.         subSubModules/ 
  7.             __init__.py 
  8.             subSubA.py 
  9.  
  10. # subA.py 
  11.  
  12. def subAFun(): 
  13.     print('Hello from subAFun'
  14.      
  15. def subAFunTwo(): 
  16.     print('Hello from subAFunTwo'
  17.  
  18. # subSubA.py 
  19.  
  20. def subSubAFun(): 
  21.     print('Hello from subSubAFun'
  22.      
  23. def subSubAFunTwo(): 
  24.     print('Hello from subSubAFunTwo'
  25.  
  26. # __init__.py from subDir 
  27.  
  28. # Adds 'subAFun()' and 'subAFunTwo()' to the 'subDir' namespace  
  29. from .subA import * 
  30.  
  31. # The following two import statement do the same thing, they add 'subSubAFun()' and 'subSubAFunTwo()' to the 'subDir' namespace. The first one assumes '__init__.py' is empty in 'subSubDir'and the second one, assumes '__init__.py' in 'subSubDir' contains 'from .subSubA import *'
  32.  
  33. # Assumes '__init__.py' is empty in 'subSubDir' 
  34. # Adds 'subSubAFun()' and 'subSubAFunTwo()' to the 'subDir' namespace 
  35. from .subSubDir.subSubA import * 
  36.  
  37. # Assumes '__init__.py' in 'subSubDir' has 'from .subSubA import *' 
  38. # Adds 'subSubAFun()' and 'subSubAFunTwo()' to the 'subDir' namespace 
  39. from .subSubDir import * 
  40. # __init__.py from subSubDir 
  41.  
  42. # Adds 'subSubAFun()' and 'subSubAFunTwo()' to the 'subSubDir' namespace 
  43. from .subSubA import * 
  44.  
  45. # main.py 
  46.  
  47. import subDir 
  48.  
  49. subDir.subAFun() # Hello from subAFun 
  50. subDir.subAFunTwo() # Hello from subAFunTwo 
  51. subDir.subSubAFun() # Hello from subSubAFun 
  52. subDir.subSubAFunTwo() # Hello from subSubAFunTwo 

表达式与控制流

条件选择

Python 中使用 if、elif、else 来进行基础的条件选择操作:

  1. if x < 0: 
  2.      x = 0 
  3.      print('Negative changed to zero'
  4.  elif x == 0: 
  5.      print('Zero'
  6.  else
  7.      print('More'

Python 同样支持 ternary conditional operator:

  1. a if condition else b 

也可以使用 Tuple 来实现类似的效果:

  1. # test 需要返回 True 或者 False 
  2. (falseValue, trueValue)[test] 
  3.  
  4. # 更安全的做法是进行强制判断 
  5. (falseValue, trueValue)[test == True
  6.  
  7. # 或者使用 bool 类型转换函数 
  8. (falseValue, trueValue)[bool(<expression>)] 

循环遍历

for-in 可以用来遍历数组与字典:

  1. words = ['cat''window''defenestrate'
  2.  
  3. for w in words: 
  4.     print(w, len(w)) 
  5.  
  6. # 使用数组访问操作符,能够迅速地生成数组的副本 
  7. for w in words[:]: 
  8.     if len(w) > 6: 
  9.         words.insert(0, w) 
  10.  
  11. # words -> ['defenestrate''cat''window''defenestrate'

如果我们希望使用数字序列进行遍历,可以使用 Python 内置的 range 函数:

  1. a = ['Mary''had''a''little''lamb'
  2.  
  3. for i in range(len(a)): 
  4.     print(i, a[i]) 

基本数据类型

可以使用内建函数进行强制类型转换(Casting):

  1. int(str) 
  2. float(str) 
  3. str(int
  4. str(float

Number: 数值类型

  1. x = 3 
  2. print type(x) # Prints "<type 'int'>" 
  3. print x       # Prints "3" 
  4. print x + 1   # Addition; prints "4" 
  5. print x - 1   # Subtraction; prints "2" 
  6. print x * 2   # Multiplication; prints "6" 
  7. print x ** 2  # Exponentiation; prints "9" 
  8. x += 1 
  9. print x  # Prints "4" 
  10. x *= 2 
  11. print x  # Prints "8" 
  12. y = 2.5 
  13. print type(y) # Prints "<type 'float'>" 
  14. print y, y + 1, y * 2, y ** 2 # Prints "2.5 3.5 5.0 6.25" 

布尔类型

Python 提供了常见的逻辑操作符,不过需要注意的是 Python 中并没有使用 &&、|| 等,而是直接使用了英文单词。

  1. t = True 
  2. f = False 
  3. print type(t) # Prints "<type 'bool'>" 
  4. print t and f # Logical AND; prints "False" 
  5. print t or f  # Logical OR; prints "True" 
  6. print not t   # Logical NOT; prints "False" 
  7. print t != f  # Logical XOR; prints "True"  

String: 字符串

Python 2 中支持 Ascii 码的 str() 类型,独立的 unicode() 类型,没有 byte 类型;而 Python 3 中默认的字符串为 utf-8 类型,并且包含了 byte 与 bytearray 两个字节类型:

  1. type("Guido") # string type is str in python2 
  2. # <type 'str'
  3.  
  4. # 使用 __future__ 中提供的模块来降级使用 Unicode 
  5. from __future__ import unicode_literals 
  6. type("Guido") # string type become unicode 
  7. # <type 'unicode'

Python 字符串支持分片、模板字符串等常见操作:

  1. var1 = 'Hello World!' 
  2. var2 = "Python Programming" 
  3.  
  4. print "var1[0]: ", var1[0] 
  5. print "var2[1:5]: ", var2[1:5] 
  6. # var1[0]:  H 
  7. # var2[1:5]:  ytho 
  8.  
  9. print "My name is %s and weight is %d kg!" % ('Zara', 21) 
  10. # My name is Zara and weight is 21 kg! 
  11. str[0:4] 
  12. len(str) 
  13.  
  14. string.replace("-"" "
  15. ",".join(list) 
  16. "hi {0}".format('j'
  17. str.find(","
  18. str.index(",")   # same, but raises IndexError 
  19. str.count(","
  20. str.split(","
  21.  
  22. str.lower() 
  23. str.upper() 
  24. str.title() 
  25.  
  26. str.lstrip() 
  27. str.rstrip() 
  28. str.strip() 
  29.  
  30. str.islower() 
  31. # 移除所有的特殊字符 
  32. re.sub('[^A-Za-z0-9]+''', mystring)  

如果需要判断是否包含某个子字符串,或者搜索某个字符串的下标:

  1. in 操作符可以判断字符串 
  2. if "blah" not in somestring:  
  3.     continue 
  4.  
  5. # find 可以搜索下标 
  6. s = "This be a string" 
  7. if s.find("is") == -1: 
  8.     print "No 'is' here!" 
  9. else
  10.     print "Found 'is' in the string." 

Regex: 正则表达式

  1. import re 
  2.  
  3. # 判断是否匹配 
  4. re.match(r'^[aeiou]', str) 
  5.  
  6. # 以第二个参数指定的字符替换原字符串中内容 
  7. re.sub(r'^[aeiou]''?', str) 
  8. re.sub(r'(xyz)', r'\1', str) 
  9.  
  10. # 编译生成独立的正则表达式对象 
  11. expr = re.compile(r'^...$'
  12. expr.match(...) 
  13. expr.sub(...) 

下面列举了常见的表达式使用场景:

  1. # 检测是否为 HTML 标签 
  2. re.search('<[^/>][^>]*>''<a href="#label">'
  3.  
  4. # 常见的用户名密码 
  5. re.match('^[a-zA-Z0-9-_]{3,16}$''Foo'is not None 
  6. re.match('^\w|[-_]{3,16}$''Foo'is not None 
  7.  
  8. # Email 
  9. re.match('^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$''hello.world@example.com'
  10.  
  11. # Url 
  12. exp = re.compile(r'''^(https?:\/\/)? # match http or https 
  13.                 ([\da-z\.-]+)            # match domain 
  14.                 \.([a-z\.]{2,6})         # match domain 
  15.                 ([\/\w \.-]*)\/?$        # match api or file 
  16.                 ''', re.X) 
  17. exp.match('www.google.com'
  18.  
  19. # IP 地址 
  20. exp = re.compile(r'''^(?:(?:25[0-5] 
  21.                      |2[0-4][0-9] 
  22.                      |[1]?[0-9][0-9]?)\.){3} 
  23.                      (?:25[0-5] 
  24.                      |2[0-4][0-9] 
  25.                      |[1]?[0-9][0-9]?)$''', re.X) 
  26. exp.match('192.168.1.1'

集合类型

List: 列表

Operation: 创建增删

  1. l = [] 
  2. l = list() 
  3.  
  4. # 使用字符串的 split 方法,可以将字符串转化为列表 
  5. str.split("."
  6.  
  7. # 如果需要将数组拼装为字符串,则可以使用 join  
  8. list1 = ['1''2''3'
  9. str1 = ''.join(list1) 
  10.  
  11. # 如果是数值数组,则需要先进行转换 
  12. list1 = [1, 2, 3] 
  13. str1 = ''.join(str(e) for e in list1) 

可以使用 append 与 extend 向数组中插入元素或者进行数组连接

  1. x = [1, 2, 3] 
  2.  
  3. x.append([4, 5]) # [1, 2, 3, [4, 5]] 
  4.  
  5. x.extend([4, 5]) # [1, 2, 3, 4, 5],注意 extend 返回值为 None 

可以使用 pop、slices、del、remove 等移除列表中元素:

  1. myList = [10,20,30,40,50] 
  2.  
  3. # 弹出第二个元素 
  4. myList.pop(1) # 20 
  5. # myList: myList.pop(1) 
  6.  
  7. # 如果不加任何参数,则默认弹出最后一个元素 
  8. myList.pop() 
  9.  
  10. # 使用 slices 来删除某个元素 
  11. a = [  1, 2, 3, 4, 5, 6 ] 
  12. index = 3 # Only Positive index 
  13. a = a[:index] + a[index+1 :] 
  14.  
  15. # 根据下标删除元素 
  16. myList = [10,20,30,40,50] 
  17. rmovIndxNo = 3 
  18. del myList[rmovIndxNo] # myList: [10, 20, 30, 50] 
  19.  
  20. # 使用 remove 方法,直接根据元素删除 
  21. letters = ["a""b""c""d""e"
  22. numbers.remove(numbers[1]) 
  23. print(*letters) # used a * to make it unpack you don't have to 

Iteration: 索引遍历

你可以使用基本的 for 循环来遍历数组中的元素,就像下面介个样纸:

  1. animals = ['cat''dog''monkey'
  2. for animal in animals: 
  3.     print animal 
  4. # Prints "cat""dog""monkey", each on its own line. 

如果你在循环的同时也希望能够获取到当前元素下标,可以使用 enumerate 函数:

  1. animals = ['cat''dog''monkey'
  2. for idx, animal in enumerate(animals): 
  3.     print '#%d: %s' % (idx + 1, animal) 
  4. # Prints "#1: cat""#2: dog""#3: monkey", each on its own line 

Python 也支持切片(Slices):

  1. nums = range(5)    # range is a built-in function that creates a list of integers 
  2. print nums         # Prints "[0, 1, 2, 3, 4]" 
  3. print nums[2:4]    # Get a slice from index 2 to 4 (exclusive); prints "[2, 3]" 
  4. print nums[2:]     # Get a slice from index 2 to the end; prints "[2, 3, 4]" 
  5. print nums[:2]     # Get a slice from the start to index 2 (exclusive); prints "[0, 1]" 
  6. print nums[:]      # Get a slice of the whole list; prints ["0, 1, 2, 3, 4]" 
  7. print nums[:-1]    # Slice indices can be negative; prints ["0, 1, 2, 3]" 
  8. nums[2:4] = [8, 9] # Assign a new sublist to a slice 
  9. print nums         # Prints "[0, 1, 8, 9, 4]" 

Comprehensions: 变换

Python 中同样可以使用 map、reduce、filter,map 用于变换数组:

  1. # 使用 map 对数组中的每个元素计算平方 
  2. items = [1, 2, 3, 4, 5] 
  3. squared = list(map(lambda x: x**2, items)) 
  4.  
  5. # map 支持函数以数组方式连接使用 
  6. def multiply(x): 
  7.     return (x*x) 
  8. def add(x): 
  9.     return (x+x) 
  10.  
  11. funcs = [multiply, add
  12. for i in range(5): 
  13.     value = list(map(lambda x: x(i), funcs)) 
  14.     print(value) 

reduce 用于进行归纳计算:

  1. # reduce 将数组中的值进行归纳 
  2.  
  3. from functools import reduce 
  4. product = reduce((lambda x, y: x * y), [1, 2, 3, 4]) 
  5.  
  6. Output: 24 

filter 则可以对数组进行过滤:

  1. number_list = range(-5, 5) 
  2. less_than_zero = list(filter(lambda x: x < 0, number_list)) 
  3. print(less_than_zero) 
  4.  
  5. Output: [-5, -4, -3, -2, -1] 

字典类型

创建增删

  1. d = {'cat''cute''dog''furry'}  # 创建新的字典 
  2. print d['cat']       # 字典不支持点(Dot)运算符取值 

如果需要合并两个或者多个字典类型:

  1. # python 3.5 
  2. z = {**x, **y} 
  3.  
  4. # python 2.7 
  5. def merge_dicts(*dict_args): 
  6.     ""
  7.     Given any number of dicts, shallow copy and merge into a new dict, 
  8.     precedence goes to key value pairs in latter dicts. 
  9.     ""
  10.     result = {} 
  11.     for dictionary in dict_args: 
  12.         result.update(dictionary) 
  13.     return result 

索引遍历

可以根据键来直接进行元素访问:

  1. # Python 中对于访问不存在的键会抛出 KeyError 异常,需要先行判断或者使用 get 
  2. print 'cat' in d     # Check if a dictionary has a given key; prints "True" 
  3.  
  4. # 如果直接使用 [] 来取值,需要先确定键的存在,否则会抛出异常 
  5. print d['monkey']  # KeyError: 'monkey' not a key of d 
  6.  
  7. # 使用 get 函数则可以设置默认值 
  8. print d.get('monkey''N/A')  # Get an element with a default; prints "N/A" 
  9. print d.get('fish''N/A')    # Get an element with a default; prints "wet" 
  10.  
  11.  
  12. d.keys() # 使用 keys 方法可以获取所有的键 

可以使用 for-in 来遍历数组:

  1. # 遍历键 
  2. for key in d: 
  3.  
  4. # 比前一种方式慢 
  5. for k in dict.keys(): ... 
  6.  
  7. # 直接遍历值 
  8. for value in dict.itervalues(): ... 
  9.  
  10. # Python 2.x 中遍历键值 
  11. for key, value in d.iteritems(): 
  12.  
  13. # Python 3.x 中遍历键值 
  14. for key, value in d.items(): 

其他序列类型

集合

  1. # Same as {"a""b","c"
  2. normal_set = set(["a""b","c"]) 
  3.   
  4. # Adding an element to normal set is fine 
  5. normal_set.add("d"
  6.   
  7. print("Normal Set"
  8. print(normal_set) 
  9.   
  10. # A frozen set 
  11. frozen_set = frozenset(["e""f""g"]) 
  12.   
  13. print("Frozen Set"
  14. print(frozen_set) 
  15.   
  16. # Uncommenting below line would cause error as 
  17. # we are trying to add element to a frozen set 
  18. # frozen_set.add("h"

函数

函数定义

Python 中的函数使用 def 关键字进行定义,譬如:

  1. def sign(x): 
  2.     if x > 0: 
  3.         return 'positive' 
  4.     elif x < 0: 
  5.         return 'negative' 
  6.     else
  7.         return 'zero' 
  8.  
  9.  
  10. for x in [-1, 0, 1]: 
  11.     print sign(x) 
  12. # Prints "negative""zero""positive" 

Python 支持运行时创建动态函数,也即是所谓的 lambda 函数:

  1. def f(x): return x**2 
  2.  
  3. # 等价于 
  4. g = lambda x: x**2 

参数

Option Arguments: 不定参数

  1. def example(a, b=None, *args, **kwargs): 
  2.   print a, b 
  3.   print args 
  4.   print kwargs 
  5.  
  6. example(1, "var", 2, 3, word="hello"
  7. # 1 var 
  8. # (2, 3) 
  9. # {'word''hello'
  10.  
  11. a_tuple = (1, 2, 3, 4, 5) 
  12. a_dict = {"1":1, "2":2, "3":3} 
  13. example(1, "var", *a_tuple, **a_dict) 
  14. # 1 var 
  15. # (1, 2, 3, 4, 5) 
  16. # {'1': 1, '2': 2, '3': 3} 

生成器

  1. def simple_generator_function(): 
  2.     yield 1 
  3.     yield 2 
  4.     yield 3 
  5.  
  6. for value in simple_generator_function(): 
  7.     print(value) 
  8.  
  9. # 输出结果 
  10. # 1 
  11. # 2 
  12. # 3 
  13. our_generator = simple_generator_function() 
  14. next(our_generator) 
  15. # 1 
  16. next(our_generator) 
  17. # 2 
  18. next(our_generator) 
  19. #3 
  20.  
  21. # 生成器典型的使用场景譬如无限数组的迭代 
  22. def get_primes(number): 
  23.     while True
  24.         if is_prime(number): 
  25.             yield number 
  26.         number += 1 

装饰器

装饰器是非常有用的设计模式:

  1. # 简单装饰器 
  2.  
  3. from functools import wraps 
  4. def decorator(func): 
  5.     @wraps(func) 
  6.     def wrapper(*args, **kwargs): 
  7.         print('wrap function'
  8.         return func(*args, **kwargs) 
  9.     return wrapper 
  10.  
  11. @decorator 
  12. def example(*a, **kw): 
  13.     pass 
  14.  
  15. example.__name__  # attr of function preserve 
  16. 'example' 
  17. # Decorator  
  18.  
  19. # 带输入值的装饰器 
  20.  
  21. from functools import wraps 
  22. def decorator_with_argument(val): 
  23.   def decorator(func): 
  24.     @wraps(func) 
  25.     def wrapper(*args, **kwargs): 
  26.       print "Val is {0}".format(val) 
  27.       return func(*args, **kwargs) 
  28.     return wrapper 
  29.   return decorator 
  30.  
  31. @decorator_with_argument(10) 
  32. def example(): 
  33.   print "This is example function." 
  34.  
  35. example() 
  36. # Val is 10 
  37. # This is example function
  38.  
  39. # 等价于 
  40.  
  41. def example(): 
  42.   print "This is example function." 
  43.  
  44. example = decorator_with_argument(10)(example) 
  45. example() 
  46. # Val is 10 
  47. # This is example function

类与对象

类定义

Python 中对于类的定义也很直接:

  1. class Greeter(object): 
  2.      
  3.     # Constructor 
  4.     def __init__(self, name): 
  5.         self.name = name  # Create an instance variable 
  6.          
  7.     # Instance method 
  8.     def greet(self, loud=False): 
  9.         if loud: 
  10.             print 'HELLO, %s!' % self.name.upper() 
  11.         else
  12.             print 'Hello, %s' % self.name 
  13.          
  14. g = Greeter('Fred')  # Construct an instance of the Greeter class 
  15. g.greet()            # Call an instance method; prints "Hello, Fred" 
  16. g.greet(loud=True)   # Call an instance method; prints "HELLO, FRED!" 
  17. # isinstance 方法用于判断某个对象是否源自某个类 
  18. ex = 10 
  19. isinstance(ex,int

Managed Attributes: 受控属性

  1. # property、setter、deleter 可以用于复写点方法 
  2.  
  3. class Example(object): 
  4.     def __init__(self, value): 
  5.        self._val = value 
  6.     @property 
  7.     def val(self): 
  8.         return self._val 
  9.     @val.setter 
  10.     def val(self, value): 
  11.         if not isintance(value, int): 
  12.             raise TypeError("Expected int"
  13.         self._val = value 
  14.     @val.deleter 
  15.     def val(self): 
  16.         del self._val 
  17.     @property 
  18.     def square3(self): 
  19.         return 2**3 
  20.  
  21. ex = Example(123) 
  22. ex.val = "str" 
  23. # Traceback (most recent call last): 
  24. #   File "", line 1, in 
  25. #   File "test.py", line 12, in val 
  26. #     raise TypeError("Expected int"
  27. # TypeError: Expected int 

类方法与静态方法

  1. class example(object): 
  2.   @classmethod 
  3.   def clsmethod(cls): 
  4.     print "I am classmethod" 
  5.   @staticmethod 
  6.   def stmethod(): 
  7.     print "I am staticmethod" 
  8.   def instmethod(self): 
  9.     print "I am instancemethod" 
  10.  
  11. ex = example() 
  12. ex.clsmethod() 
  13. # I am classmethod 
  14. ex.stmethod() 
  15. # I am staticmethod 
  16. ex.instmethod() 
  17. # I am instancemethod 
  18. example.clsmethod() 
  19. # I am classmethod 
  20. example.stmethod() 
  21. # I am staticmethod 
  22. example.instmethod() 
  23. # Traceback (most recent call last): 
  24. #   File "", line 1, in 
  25. # TypeError: unbound method instmethod() ... 

对象

实例化

属性操作

Python 中对象的属性不同于字典键,可以使用点运算符取值,直接使用 in 判断会存在问题:

  1. class A(object): 
  2.     @property 
  3.     def prop(self): 
  4.         return 3 
  5.  
  6. a = A() 
  7. print "'prop' in a.__dict__ ="'prop' in a.__dict__ 
  8. print "hasattr(a, 'prop') =", hasattr(a, 'prop'
  9. print "a.prop =", a.prop 
  10.  
  11. 'prop' in a.__dict__ = False 
  12. # hasattr(a, 'prop') = True 
  13. # a.prop = 3 

建议使用 hasattr、getattr、setattr 这种方式对于对象属性进行操作:

  1. class Example(object): 
  2.   def __init__(self): 
  3.     self.name = "ex" 
  4.   def printex(self): 
  5.     print "This is an example" 
  6.  
  7.  
  8. Check object has attributes 
  9. # hasattr(obj, 'attr'
  10. ex = Example() 
  11. hasattr(ex,"name"
  12. True 
  13. hasattr(ex,"printex"
  14. True 
  15. hasattr(ex,"print"
  16. False 
  17.  
  18. # Get object attribute 
  19. # getattr(obj, 'attr'
  20. getattr(ex,'name'
  21. 'ex' 
  22.  
  23. Set object attribute 
  24. # setattr(obj, 'attr', value) 
  25. setattr(ex,'name','example'
  26. ex.name 
  27. 'example' 

异常与测试

异常处理

Context Manager - with

with 常用于打开或者关闭某些资源:

  1. host = 'localhost' 
  2. port = 5566 
  3. with Socket(host, port) as s: 
  4.     while True
  5.         conn, addr = s.accept() 
  6.         msg = conn.recv(1024) 
  7.         print msg 
  8.         conn.send(msg) 
  9.         conn.close() 

单元测试

  1. from __future__ import print_function 
  2.  
  3. import unittest 
  4.  
  5. def fib(n): 
  6.     return 1 if n<=2 else fib(n-1)+fib(n-2) 
  7.  
  8. def setUpModule(): 
  9.         print("setup module"
  10. def tearDownModule(): 
  11.         print("teardown module"
  12.  
  13. class TestFib(unittest.TestCase): 
  14.  
  15.     def setUp(self): 
  16.         print("setUp"
  17.         self.n = 10 
  18.     def tearDown(self): 
  19.         print("tearDown"
  20.         del self.n 
  21.     @classmethod 
  22.     def setUpClass(cls): 
  23.         print("setUpClass"
  24.     @classmethod 
  25.     def tearDownClass(cls): 
  26.         print("tearDownClass"
  27.     def test_fib_assert_equal(self): 
  28.         self.assertEqual(fib(self.n), 55) 
  29.     def test_fib_assert_true(self): 
  30.         self.assertTrue(fib(self.n) == 55) 
  31.  
  32. if __name__ == "__main__"
  33.     unittest.main() 

存储

文件读写

路径处理

Python 内置的 __file__ 关键字会指向当前文件的相对路径,可以根据它来构造绝对路径,或者索引其他文件:

  1. # 获取当前文件的相对目录 
  2. dir = os.path.dirname(__file__) # src\app 
  3.  
  4. ## once you're at the directory level you want, with the desired directory as the final path node: 
  5. dirname1 = os.path.basename(dir)  
  6. dirname2 = os.path.split(dir)[1] ## if you look at the documentation, this is exactly what os.path.basename does. 
  7.  
  8. # 获取当前代码文件的绝对路径,abspath 会自动根据相对路径与当前工作空间进行路径补全 
  9. os.path.abspath(os.path.dirname(__file__)) # D:\WorkSpace\OWS\tool\ui-tool-svn\python\src\app 
  10.  
  11. # 获取当前文件的真实路径 
  12. os.path.dirname(os.path.realpath(__file__)) # D:\WorkSpace\OWS\tool\ui-tool-svn\python\src\app 
  13.  
  14. # 获取当前执行路径 
  15. os.getcwd() 

可以使用 listdir、walk、glob 模块来进行文件枚举与检索:

  1. # 仅列举所有的文件 
  2. from os import listdir 
  3. from os.path import isfile, join 
  4. onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))] 
  5.  
  6. # 使用 walk 递归搜索 
  7. from os import walk 
  8.  
  9. f = [] 
  10. for (dirpath, dirnames, filenames) in walk(mypath): 
  11.     f.extend(filenames) 
  12.     break 
  13.  
  14. # 使用 glob 进行复杂模式匹配 
  15. import glob 
  16. print(glob.glob("/home/adam/*.txt")) 
  17. # ['/home/adam/file1.txt''/home/adam/file2.txt', .... ] 

简单文件读写

  1. # 可以根据文件是否存在选择写入模式 
  2. mode = 'a' if os.path.exists(writepath) else 'w' 
  3.  
  4. # 使用 with 方法能够自动处理异常 
  5. with open("file.dat",mode) as f: 
  6.     f.write(...) 
  7.     ... 
  8.     # 操作完毕之后记得关闭文件 
  9.     f.close() 
  10.  
  11. # 读取文件内容 
  12. message = f.read() 

复杂格式文件

JSON

  1. import json 
  2.  
  3. # Writing JSON data 
  4. with open('data.json''w'as f: 
  5.      json.dump(data, f) 
  6.  
  7. # Reading data back 
  8. with open('data.json''r'as f: 
  9.      data = json.load(f) 

XML

我们可以使用 lxml 来解析与处理 XML 文件,本部分即对其常用操作进行介绍。lxml 支持从字符串或者文件中创建 Element 对象:

  1. from lxml import etree 
  2.  
  3. # 可以从字符串开始构造 
  4. xml = '<a xmlns="test"><b xmlns="test"/></a>' 
  5. root = etree.fromstring(xml) 
  6. etree.tostring(root) 
  7. # b'<a xmlns="test"><b xmlns="test"/></a>' 
  8.  
  9. # 也可以从某个文件开始构造 
  10. tree = etree.parse("doc/test.xml"
  11.  
  12. # 或者指定某个 baseURL 
  13. root = etree.fromstring(xml, base_url="http://where.it/is/from.xml"

其提供了迭代器以对所有元素进行遍历:

  1. # 遍历所有的节点 
  2. for tag in tree.iter(): 
  3.     if not len(tag): 
  4.         print tag.keys() # 获取所有自定义属性 
  5.         print (tag.tag, tag.text) # text 即文本子元素值 
  6.  
  7. # 获取 XPath 
  8. for e in root.iter(): 
  9.     print tree.getpath(e) 

lxml 支持以 XPath 查找元素,不过需要注意的是,XPath 查找的结果是数组,并且在包含命名空间的情况下,需要指定命名空间:

  1. root.xpath('//page/text/text()',ns={prefix:url}) 
  2.  
  3. # 可以使用 getparent 递归查找父元素 
  4. el.getparent() 

lxml 提供了 insert、append 等方法进行元素操作:

  1. # append 方法默认追加到尾部 
  2. st = etree.Element("state"name="New Mexico"
  3. co = etree.Element("county"name="Socorro"
  4. st.append(co) 
  5.  
  6. insert 方法可以指定位置 
  7. node.insert(0, newKid) 

Excel

可以使用 [xlrd]() 来读取 Excel 文件,使用 xlsxwriter 来写入与操作 Excel 文件。

  1. # 读取某个 Cell 的原始值 
  2. sh.cell(rx, col).value 
  3. # 创建新的文件 
  4. workbook = xlsxwriter.Workbook(outputFile) 
  5. worksheet = workbook.add_worksheet() 
  6.  
  7. # 设置从第 0 行开始写入 
  8. row = 0 
  9.  
  10. # 遍历二维数组,并且将其写入到 Excel 中 
  11. for rowData in array: 
  12.     for col, data in enumerate(rowData): 
  13.         worksheet.write(row, col, data) 
  14.     row = row + 1 
  15.  
  16. workbook.close() 

文件系统

对于高级的文件操作,我们可以使用 Python 内置的 shutil

  1. # 递归删除 appName 下面的所有的文件夹 
  2. shutil.rmtree(appName) 

网络交互

Requests

Requests 是优雅而易用的 Python 网络请求库:

  1. import requests 
  2.  
  3. r = requests.get('https://api.github.com/events'
  4. r = requests.get('https://api.github.com/user', auth=('user''pass')) 
  5.  
  6. r.status_code 
  7. # 200 
  8. r.headers['content-type'
  9. 'application/json; charset=utf8' 
  10. r.encoding 
  11. 'utf-8' 
  12. r.text 
  13. # u'{"type":"User"...' 
  14. r.json() 
  15. # {u'private_gists': 419, u'total_private_repos': 77, ...} 
  16.  
  17. r = requests.put('http://httpbin.org/put', data = {'key':'value'}) 
  18. r = requests.delete('http://httpbin.org/delete'
  19. r = requests.head('http://httpbin.org/get'
  20. r = requests.options('http://httpbin.org/get'

数据存储

MySQL

  1. import pymysql.cursors 
  2.  
  3. Connect to the database 
  4. connection = pymysql.connect(host='localhost'
  5.                              user='user'
  6.                              password='passwd'
  7.                              db='db'
  8.                              charset='utf8mb4'
  9.                              cursorclass=pymysql.cursors.DictCursor) 
  10.  
  11. try: 
  12.     with connection.cursor() as cursor
  13.         # Create a new record 
  14.         sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)" 
  15.         cursor.execute(sql, ('webmaster@python.org''very-secret')) 
  16.  
  17.     # connection is not autocommit by default. So you must commit to save 
  18.     # your changes. 
  19.     connection.commit() 
  20.  
  21.     with connection.cursor() as cursor
  22.         # Read a single record 
  23.         sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s" 
  24.         cursor.execute(sql, ('webmaster@python.org',)) 
  25.         result = cursor.fetchone() 
  26.         print(result) 
  27. finally: 
  28.     connection.close()  

【本文是51CTO专栏作者“张梓雄 ”的原创文章,如需转载请通过51CTO与作者联系】

戳这里,看该作者更多好文

【编辑推荐】

  1. Python这么简单还用学吗?
  2. DDD实战篇:分层架构的代码结构
  3. 陈罡:大规模定制实战应用分|V课堂第90期
  4. 综述论文:当前深度神经网络模型压缩和加速方法速览
  5. 在Python和TensorFlow上构建Word2Vec词嵌入模型
【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

热门职位+更多