Python Basis

Start learning python

Posted by Chaoran on December 30, 2017

“Yeah It’s on. ”

python

1. 语言特性:

强类型(大小写敏感)
面向对象(一切皆为对象)

2. 获取帮助

help(<object>)
dir()显示该对象的所有方法
<object>._d显示其文档

3. 语法

  • (#)井号表示之后为字符为python的注释
  • (“”” a = 1 “””) 多行注释
  • (\n)换行是标准的行分隔符
  • (\)反斜线表示继续上一行
  • (;)分隔同一行多个语句
  • (:)冒号表示将代码块的头和体分开
  • 语句(代码块)用于缩进的方式体现
  • 不同的缩进深度分隔不同的代码块
  • python文件以模块的形式组织
  • 赋值
    # python 中对象通过引用传递
    x = x+1   # 增量赋值
    x += 1
    
    # 多重赋值
    x = y = z = 1  # 将同一个引用赋值给x,y,z
    
    # 多元赋值
    (x,y,z)=(1,2,'a string')
    
  • 标识符
    • 第一个字符必须是字母或者下划线(_)
    • 剩下的字符可以是字符和数字或下划线。
    • 大小写敏感
  • 变量(避免下划线开头,无需声明)
    • xxx 系统定义名字
    • _xxx 类中的私有变量名
  • 内存管理
    • 变量无须事先声明
    • 变量无须指定类型
    • 程序员不用关心内存管理
    • 变量名会被“回收”
    • del语句能够直接释放资源

4. 数据类型

列表(list)、元组(tuple)、字典(dictionaries)三种基本数据结构

常量:大写

  1. List: 内置数据类型,有序集合,元素类型可不同,可随时添加和删除元素:.insert(i) .pop(i)
  2. Tuple: 初始化后不能修改 python-js

5. dict 和 set

  1. dict的key必须是不可变对象
  2. set和dict类似,也是一组key的集合,但不存储value,无重复元素(两个set可以做数学意义上的交集、并集等操作) 和list比较,dict有以下几个特点:
    • 查找和插入的速度极快,不会随着key*的增加而增加;
    • 需要占用大量的内存,内存浪费多。 而list相反:
    • 查找和插入的时间随着元素的增加而增加;
    • 占用空间小,浪费内存很少。 所以,dict是用空间来换取时间的一种方法。

6. 流程控制

if for while range():生成一个有数字组成的列表

7. 函数

def声明 参数通过引用传递,但对于不可变类型(元组、整数、字符串)不改变

7.1. 默认参数

指向不变对象(str,None)

7.2. 可变参数
def calc(*num)
7.3. 关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

    def person(name, age, **kw):
        print 'name:', name, 'age:', age, 'other:', kw
    
    >>> person('Bob', 35, city='Beijing')
        name: Bob age: 35 other: {'city': 'Beijing'}

    # 用 in 和 not in 来检查某个键是否在字典中
7.4. 参数组合

参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。

    def func(a, b, c=0, *args, **kw):
        print 'a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw
    # *args是可变参数,args接收的是一个tuple;
    # **kw是关键字参数,kw接收的是一个dict。
7.5. 递归函数

尾递归优化

def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)
7.6. 切片

L[0:3](表示从索引0开始到索引3为止,0,1,2)

L = range(100)
L[:10]      # 前10个数
L[-10:]     # 后10个数
L[:10:2]    #前10个数,每两个取一个
L[::5]      #所有数,每5个取一个
L[:]        #复制一个list
7.7. 迭代 for … in
d = {'a': 1, 'b': 2, 'c': 3}
for key in d            # 迭代key
for value in d.itervalues()  # 迭代value
for k, v in d.iteritems()    # 迭代key,value

# 判断是否为可迭代对象-通过collections模块的iterable类型判断
from collections import Iterable
isinstance('abc', Iterable) # str是否可迭代 true

7.8. 列表生成式
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 还可以加上if判断
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
7.9. 生成器

列表元素可以按照某种算法推算出来,节省空间

# 将[]直接换成()
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x104feab40>

# 可用next()或for循环
>>> g.next()
0
>>> g.next()
1

8. 函数式编程

8.1. 高阶函数
  1. map 接受两个参数(函数,序列) 将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

     >>> def f(x):
     ...     return x * x
     ...
     >>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
     [1, 4, 9, 16, 25, 36, 49, 64, 81]
    
  2. reduce reduce把一个函数作用在一个序列[x1, x2, x3…]上 必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算

     reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
    
     # 比方说对一个序列求和,就可以用reduce实现:
     >>> def add(x, y):
     ...     return x + y
     ...
     >>> reduce(add, [1, 3, 5, 7, 9])
     25
    
  3. filter 与map 类似:接收参数:一个函数、一个序列 不同:依次作用于每个元素,根据返回值true/false决定是否保留

     def not_empty(s):
             return s and s.strip()
    
     filter(not_empty, ['A', '', 'B', None, 'C', '  '])
     # 结果: ['A', 'B', 'C']
    
  4. sorted
  5. lambda 限制:只能有一个表达式,不用写return,返回值就是该表达式的结果

     lambda x: x * x
     # 相当于
     def f(x):
             return x * x
    

9. 模块

9.1. 模块格式
#!/usr/bin/env python    ——标准注释:该注释可以让此文件直接在Unix/Linux/Mac上运行
# -*- coding: utf-8 -*-  ——标准注释:表示此文件本身使用标准UTF-8编码

' a test module '   # 模块的文档注释——任何模块代码的第一个字符串都被视为模块的文档注释

__author__ = 'Michael Liao'  # 作者名字

import sys   # 导入模块,模块argv变量用list存储了命令行所有参数
# 运行python hello.py获得的sys.argv就是['hello.py'];

# 运行python hello.py Michael获得的sys.argv就是['hello.py', 'Michael]。

def test():
    args = sys.argv
    if len(args)==1:
        print 'Hello, world!'
    elif len(args)==2:
        print 'Hello, %s!' % args[1]
    else:
        print 'Too many arguments!'

if __name__=='__main__':
    test()
9.2 作用域
  • public: abc,x123
  • 特殊变量: xxx 可被直接引用(特殊用途如:author,name
    • __name__指示模块应如何被加载
    • 如果模块是被导入,__name__的值为模块名字
    • 如果模块是被直接执行,name__的值为‘ __main
  • private: _xxx/__xxx,不应该直接引用
def _private_1(name):
    return 'Hello, %s' % name

def _private_2(name):
    return 'Hi, %s' % name

def greeting(name):
    if len(name) > 3:
        return _private_1(name)
    else:
        return _private_2(name)
# 模块公开greeting函数,内部逻辑用private隐藏
# 外部不需要引用的函数全部定义成private,只有需要引用的函数public

10. 面向对象编程

数据封装、继承和多态只是面向对象程序设计中最基础的3个概念 私有变量/方法(惯例):至少两个前导下划线&至多尾随一个下划线(__spam)

  • python 中任何类型的值都是一个对象
  • None——Python的Null对象
    10.1 与面向过程
# 面向过程
    # 成绩表示
std1 = { 'name': 'Michael', 'score': 98 }
std2 = { 'name': 'Bob', 'score': 81 }
    # 成绩处理
def print_score(std):
    print '%s: %s' % (std['name'], std['score'])

# 面向对象
class Student(object):  # class 类名(-大写开头) (object-继承哪个类)
    def __init__(self, name, score): # 创建实例时绑定必要属性
        self.name = name     # self:创建的实例本身
        self.score = score

    def print_score(self):
        print '%s: %s' % (self.name, self.score)

# 对象操作
bart = Student('Bart Simpson', 59)  # 类名+() 创建实例
lisa = Student('Lisa Simpson', 87)
lisa.school = 'huagong'          # 可自由绑定属性
bart.print_score()
lisa.print_score()

# 访问限制
# 之前还能访问name,score属性,若限制保护内部变量
self.__name = name
self.__score = score
# 原因:Python解释器对外把__name变量改成了_Student__name
>>> bart._Student__name
'Bart Simpson'

# 获取方法 
# 给Student类增加get_name和get_score
class Student(object):
    ...
    def get_name(self):
        return self.__name
    
    def set_score(self, score):  # 修改
        self.__score = score
10.2. 与普通函数
第一个参数永远是实例变量self,调用时不用传递该参数 特点
- 类是创建实例的模板,而实例则是一个个具体对象,各个实例拥有的数据都互相独立
- 方法就是与实例绑定的函数,可以直接访问实例的数据
- 允许对实例变量绑定任何数据,不同实例变量可能不同
10.3. 多态
class Animal(object):
    def run(self):
        print 'Animal is running...'

class Dog(Animal):
    def run(self):
        print 'Dog is running...'

dog = Dog()
>>> dog.run()
>>> Dog is running...
10.4. 判断变量类型
# 判断一个变量是否是某个类型可以用isinstance()判断:
a = list() # a是list类型
b = Animal() # b是Animal类型

>>> isinstance(a, list)
True
>>> isinstance(b, Animal)
True

11. 获取对象信息

11.1. type()

判断基本类型

>>> type(123)
<type 'int'>
>>> type('str')
<type 'str'>
>>> type(None)
<type 'NoneType'>
# 函数或类
>>> type(abs)
<type 'builtin_function_or_method'>
>>> type(a)
<class '__main__.Animal'>

# types模块
>>> import types
>>> type('abc')==types.StringType
True
>>> type([])==types.ListType
True
>>> type(str)==types.TypeType  # 所有类型本身的类型就是TypeType
True
11.2. isinstance()

判断class类型

h = Husky()

>>> isinstance(h, Husky) # 父类也可以
True

# 基本类型也可以
>>> isinstance('a', str)
True
# 判断是否属于一种
>>> isinstance('a', (str, unicode))
True
11.3. dir()

获取对象的所有属性和方法

dir('abc')

配合getattr()、setattr()以及hasattr(),可以直接操作一个对象的状态:

>>> class MyObject(object):
	     def __init__(self):
         self.x = 9
	     def power(self):
	         return self.x * self.x

>>> obj = MyObject()
紧接着,可以测试该对象的属性:

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'  
19
>>> obj.y # 获取属性'y'
19
# 若不存在,返回默认值
>>> getattr(obj, 'z', 404)
404

11. 面向对象高级编程

11.1. slots

限制class属性,仅对当前类起作用,对继承的子类不起作用

class Student(object):
  __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

s = Student() # 创建新的实例
s.score = 99 # 绑定属性'score'
# 由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。
11.2. @property

用在类定义中,将方法转化为属性,代码简短,调用简单

class Student(object):
  def get_score(self):
    return self._score

  def set_score(self, value):
    if not isinstance(value, int):
        raise ValueError('score must be an integer!')
    if value < 0 or value > 100:
        raise ValueError('score must between 0 ~ 100!')
    self._score = value

>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60

# 转化为可直接调用的属性
class Student(object):

  @property
  def score(self):
    return self._score

  @score.setter
  def score(self, value):
    if not isinstance(value, int):
      raise ValueError('score must be an integer!')
    if value < 0 or value > 100:
      raise ValueError('score must between 0 ~ 100!')
    self._score = value

>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
11.3. 多重继承

子类同时获得多个父类的所有功能

class Dog(Mammal, Runnable):
  pass

# mixin
# python自带功能库

12. 异常

try-except[exceptionname]

try:
  print 'try...'
  r = 10 / 0
  print 'result:', r
except ZeroDivisionError, e:
  print 'except:', e
else: 
  print 'no error!'
finally:
  print 'finally...'
print 'END'

# 结果
try...
except: integer division or modulo by zero
finally...
END

13. 调试

  1. print
  2. assert
  # err.py
  def foo(s):
      n = int(s)
      assert n != 0, 'n is zero!'
      return 10 / n

  def main():
      foo('0')

  # 若断言失败
  $ python err.py
  Traceback (most recent call last):
    ...
  AssertionError: n is zero!

  # 关闭断言
  $ python -O err.py
  1. logging

14. IO

14.1. 文件读写
  1. 读文件
# open()函数,传入文件名和标示符
f = open('/Users/michael/test.txt', 'r')
# read()方法一次读取文件的全部内容,把内容读到内存,用一个str对象表示
f.read()   # 'Hello, world!'

# close()方法关闭文件(以防占用操作系统的资源)
f.close()

# IOError,一旦出错,后面的f.close()不会调用
# 为了保证无论是否出错都能正确地关闭文件,使用try ... finally
try:
    f = open('/path/to/file', 'r')
    print f.read()
finally:
    if f:
        f.close()

# with语句: 自动调用close
with open('/path/to/file', 'r') as f:
    print f.read()

其他读取方式

read()      # 一次性读取文件的全部内容
readline()  # 每次读取一行内容
readlines() # 一次读取所有内容并按行返回list

其他文件

# file-like object
# 像open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object
# 二进制文件(图片、视频等等)
f = open('/Users/michael/test.jpg', 'rb')
f.read()
  1. 写文件

    区别:调用open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件

f = open('/Users/michael/test.txt', 'w')
f.write('Hello, world!')
f.close()

# 写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘
# with 保险方法
with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')