Python基础
基于Python2.7学习
(一)概述
一、为什么学Python
- 语法简单,易上手;
- 丰富的库支持,对Json支持,http、ftp、file、进程等;
- 完整的生态圈,一切皆有可能(大数据,云计算,自动化运维等常见);
结合unix-shell和C的使用习惯,在2000年发布2.0实现垃圾回收和Unicode支持。
二、特点
- 免费开源
- 动态数据类型,高层语言(没有类型检查)
- 可移植行,个别模块跟操作系统os有关
- 面向对象
- 可扩展性,底层用C实现
- 丰富的标准库
三、生态圈
- 不同解释器支持
- web应用开发
- 科学计算与大数据分析
- 云计算
几种解释器:
- Cpython解释器:C语言实现,常见解释器;
- Jython解释器:JVM,Java库;
- IronPython:.NET
- pypy:基于JIT的python解释器,即时编译;
四、Python web开发框架
- Django,最流行和成熟的web开发框架
- Tornado,Facebook开发的高性能web服务
- Uliueb,国人开发的web框架
- Flask
五、Python社区
华蟒用户组,中文社区
啄木鸟社区
豆瓣Python小组
六、安装Django
pip install django --index-url=http://pypi.douban.com/simple
python manage.py install
(二)Python基础
一、Python参数传递
参数传递顺序依次:
- 位置参数传递
- 关键字传递
- 表传递(列表)
- 字典传递
位置参数传递:值传递;
关键字传递:根据每个参数的名字传递;
表传递:表传递给函数的是一个指针,指针指向序列在内存中的位置;
字典传递:包裹传参;
例如:
def f(a, b=None, c=3, *args, **kwargs):
pass
混合传参顺序:先位置,再关键字,再包裹位置,再包裹关键字;
关键字传参与位置传参混用时,位置传参须在关键字传参之前;
def foo(name, count=1, *args, **kwargs):
print name
print count
print args
print kwargs
foo("python", 12, *(13,14,15), **{'a':1, 'b':2})
foo("python", *(13,14,15), **{'a':1, 'b':2})
二、MVT架构
MVT架构三、Django框架
- 包管理器安装
pip install django --index-url http://pypi.douban.com/simple
仓库:
http://pypi.douban.com/simple # 豆瓣python模块镜像
http://pypi.python.org/pypi # 中央仓库
- 从源码安装
下载Django的压缩包并解压;然后执行:
python setup.py install
- 创建第一个Django的project
django-admin.py startproject [projname]
项目目录结构:
manage.py # Django应用的管理工具
project/
settings.py # 整个项目的核心配置文件,数据库、缓存、session等
urls.py # URL转发的配置文件
wsgi.py
manage.py:管理Django项目命令行工具,支持多个命令,支持扩展自定义的命令,创建数据库schema,启动内嵌的应用服务器;
python manage.py [subcomand]
python manage.py help
settings.py:整个项目的核心配置文件
- 数据库的连接信息
- 缓存配置
- session配置
- 静态文件配置,比如:css、js
- 用户自定义信息
运行app:
python manage.py startapp [app name]
- ORM
- Django原生支持关系映射;
- 每个APP的models.py里面包含了schema的信息;
- 每次启动项目的时候,都会去验证models.py中的schema和数据库中表对应结构的一致性;
- 通过
python manage.py syncdb
来创建表;
model类:
每个model类表示一张表,生成的数据库表的名字默认是APP的名字_类的名字
;
每个model类里面都有多个Filed的Instance变量;
primary key:
默认情况下每个Model类,Django都会自动添加一个id的Integer Field变量作为主键;
用户也可以自己指定pk字段,默认就可以;
Query:
[Model Class].Objects.get()
eg. Blog.Objects.get(pk=1)
[Model Class].Objects.[filter/exclude] # 根据特定条件筛选记录
[Model Class].Objects.all() # 返回表中的全部数据
QuerySet:
Filter/exclude/all :三个API返回都是一个QuerySet的对象;
QuerySet :可以理解为Model实例的集合;
Lazy Mode :真正Query时查询,不是时时查询;
QuerySet in Chain :
Blog.Objects.all().filter(count_it=10)
ORM缺陷:
需要先手工创建一个空的数据库,无法更新schema的变量;第三方解决http://south.aeracode.org/,自Django1.7+,migration被构建到Django核心模块中,可以使用migration工具迁移schema,更新数据库。
- URL与视图的映射
- 无参数的映射
url(r'^test/$', get_blog_view)
- 带位置参数的映射
url(r'^(\d{4})/$', get_blog_view)
def get_blog_view(req, bid):
pass
- 关键字参数的映射
url(r'^(?P<blog id>\d{4})/$', get_blog_view)
def get_blog_view(req, blogid):
pass
URL采用最先匹配原则,匹配范围大的URL放在最后。
- Template
{...} 变量
{% ... %} 模板标签
{% IF %} ... {% END IF %}
{% FOR %} ... {% END FOR %}
模板上下文:
视图函数返回一个模板的时候,需要传入一个上下文(Context),Context是一个字典,key表示的是模板中的变量名字,value表示渲染完成后实际展示在HTML中的内容。
def ament_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})
模板继承:
css、HEADER、FOOTER写一次,其他模块可用
通过Block ... Extend
继承
静态文件处理:
JS、CSS等静态文件的请求处理,settings.py中的STATIC
变量指定了静态文件的根目录。
四、Python语法
- 编写脚本文件在第一行添加代码
#!/usr/bin/python
#!/usr/local/bin/python
在第二行添加:
# coding:utf8
#-*- coding:utf8 -*-
- 链式赋值:
a, b = "django", 2
python不支持A++,A--操作;
Python3:只支持长整型;
切片操作:slice
布尔值:True ,False
dict[key] 查找,效率为O(1)
字典中key唯一,可以Hash的值。
dict[key]查找,也可以用key in dict方式来判断字典是否包含key的键。
- 循环语句
for ... :
...
else:
...
当for, while正常循环退出时,会执行else语句;当for, while非正常退出时,不会执行else语句;
非正常退出,相当于break
try ... :
...
except _, e:
...
except e2:
...
else:
...
finally:
...
不抛异常时,执行else语句
- Python多重继承
Class A(ParentA, ParentB, ...):
pass
__init__
是Class构造函数,用来初始化对象
isDuplicate(s) # s是一个字符串,是否含有重复的字符
isPalindrome(s) # s是一个字符串,字符串是否是回文
- 搜索路径
Python会在以下路径中搜索他想要的寻找的模块:
- 程序所在文件夹
- 标准库的安装路径
- 操作系统环境变量PYTHONPATH所包含的路径
- Python解释器负责内存管理
id():返回对象的内存地址
引用计数为0时,GC才回收内存
整型缓冲池:整型数据被放到一个缓冲池中
a=1
b=1
id(a)与id(b)一样,用来判断是否为同一对象。
is:用来判断两个变量是不是指向同一个内存对象
python缓存整数和短字符串,因此每个对象只存有一份,所有整数的引用都指向同一个对象。即使使用赋值语句,也只是创造了新的引用,而不是对象本身。
- 包管理器
pip是Python自带的包管理程序
pip install web.py
pip uninstall web.py
pip install --upgrade web.py
which python # 查看Python安装路径
whereis python # 查看Python安装路径
pip install --install-option="--prefix=/home/vamei/util/" web.py # 模块安装路径:/home/vamei/util/
- global
def func1():
global i
global lock
if __name__ == "__main__":
i = 100
lock = threading.Lock()
func1()
在函数中使用global声明全局变量;i、lock为不可变数据对象,被当作一个局部变量,所以用global声明;
对于可变数据对象,则不需要global声明;可以将可变数据对象作为参数来传递给线程函数,这些线程将共享这些可变数据对象。
- 线程
在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie),所以有必要对每个process对象调用join()方法(实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。
多线程,可以使用共享资源,比如使用全局变量或传递参数。
多进程应避免共享资源,每个进程有自己独立的内存空间,可以通过共享内存和Manager的方法共享资源。 - 列表解析
列表解析比for循环性能好很多
[expr for iter in iterable [if condition]] # 列表解析
filter(function, iter):用来对列表中的元素进行过滤,function返回false时,该元素就被丢弃。
map(function, iter):把function(x)作用于列表的每一个元素,然后函数的结果根据顺序构成一个新的列表返回。
列表解析缺点:
内存使用效率较低,每次都要把被操作的列表中的元素一次性装载到内存里。
另一个解决方案:生成器表达式
- 每次只加载一个元素到内存中
- 返回一个可迭代的对象
- 生成器表达式
(expr for iter in iterable [if condition]) # 返回generator对象
res = (expr for iter in iteralbe [if condition])
for i in res:
print i
对内存要求较高时,使用生成器表达式
返回范围较大的列表时用xrange
- 字典和集合
字典:任何一个可以被Hash的数据类型都可以用作key;字典是无序的,值可以是任意数据类型;基于Hash表实现。
类实例做key,需要类实现__hash__
方法返回哈希值。
列表不可以做key,字典本身不能做key
元组可以做key,但要求元组中不包含列表、字典等可变类型的数据结构。
使用hash()函数来检查是否可以用作key
字符串可以做key
d = {'a':1, 'b':2}
d = dict(a=1, b=2)
d.get('c', 'Default') # 若字典中没有key为c,则返回默认值Default
d.keys() # 返回已存在的key的可迭代对象
if 'a' in d:
print e.get('a') # 使用in判断key是否在字典中
集合:元素不可重复,一组无序排列的可哈希的值,支持Union、intersection等。
set:可变集合,值是可哈希的
frozenset:不可变集合
in
:判断是否存在,for
:遍历
集合操作函数:
更新集合:add、remove、update
高级操作:
- union:联合(|)
- intersection:交集(&)
- difference:差集(-)
- symmetric_difference:异或(^)
五、函数式编程
- 函数对象
def foo():
pass
foo:函数对象
foo():函数调用
a = foo
a() # 等价函数调用foo()
不支持重载,在同一模块中定义相同名字的函数,无论参数个数,后定义的一个会覆盖之前的那个。
可以返回多个值,以元组形式返回,也可以用多个变量接收返回的多个值。
- lambda
返回可调用的函数对象
不需要return来返回结果
函数声明和定义均在一行
foo = lambda x : x+1 if x > 10 else x - 10
foo(1)
- 变量查找顺序
- 局部作用域
- 全局作用域
- global关键字
- 闭包
def fx(x):
def gy(y):
return x + y
return gy
foo = fx(5)
print foo(10) # 结果15
装饰器:被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理、Web权限校验、Cache等。
- 无参数decorator
生成一个新的装饰器函数 - 有参decorator
有参装饰,装饰函数先处理参数,再生成一个新的装饰器函数,然后对函数进行装饰。
- 面向对象编程
特征:
- 抽象/实现
- 封装/接口
- 合成
- 派生/继承
- 多态
- 自省/反射
class A(): # 经典类
pass
class B(object): # 新式类
pass
建议使用新式类,新式类必须有一个父类;
可使用type()测试,type(A)和type(B)
type(A):返回<type 'classobj'>
type(B):返回<type 'type'>
调用父类的__init__
方法:
A.__init__(self) # 经典类
super(B, self).__init__()
实例方法:
方法定义在类中,第一个位置参数为self,self表示实例对象的本省,只能被实例所调用;在调用实例方法时,不需显示地传入self,解释器默认传入。
Python构造函数:__init__
,但不是真正的构造函数,不会创建对象。
使用__new__
来构造对象
使用__init__
来初始化对象
当使用A()创建实例时,默认使用__init__
方法初始化对象。
类变量和实例变量:
类变量绑定在类上,实例共享;实例变量绑定在实例对象上,通常使用self.x来表示实例变量。给实例对象赋值时,默认创建实例变量;在查找时,先查找对象本身的属性实例变量,再查找类的属性类变量。
class A(object):
author = "Guido"
def __init__(self, page):
self.page = page
book_a = A(10)
book_b = A(100)
book_a.author = "python"
print book_a.author # 输出"python",author作为book_a的实例变量
print book_b.author # 输出"Guido",没有赋值,使用类变量,可用id()检查
- 类方法和静态方法
类方法的第一个位置参数不是self,而是cls,表示绑定到类上。
使用@staticmethod
来装饰一个静态方法,静态方法不需要self和cls。
使用@classmethod
来装饰一个类函数。
类方法:
@classmethod
def class_method(cls):
pass
静态方法:
@staticmethod
def static_method(msg):
print "[" + msg + "]"
子类若没有自己定义__init__
方法,会默认调用基类的__init__
方法;
若子类定义了__init__
方法,则需要显式调用基类的__init__
方法,并且传入self参数;
super()
:只工作在新式类
dir()
:查看对象所有属性和方法
__dict__
:类的字典属性
__doc__
:类的文档属性
__new__
:类函数,构造对象
__init__
:初始化对象
__del__
:当对象的引用计数为0时,自动调用,释放内存,要首先调用基类的__del__
__X
:定义private变量,只有类的内部可以引用
对于实例对象不存在的属性进行赋值,会动态创建这个属性,新式类可以通过设定__slot__
的类属性来防止这个问题。
issubclass(sub, sup) # 判断是否为子类
isinstance(obj, classType) # 判断是否为类的实例
super(A, self) 返回Instance
super(A, cls) 返回type
- 单元测试
- nose
- pytest
namespace:相当于字典
模块中的变量相当于单例模式
hashcod要求唯一,计算下标
- Python单例模式
class A(object):
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = object.__new__(cls, *args, **kwargs)
return cls.instance
print id(A())
print id(A()) # 值相同
- python常用模块
模块文档API:
https://docs.python.org/2/library/
使用场景:
- 操作系统相关
- 文件路径处理
- 网络处理
- 数据处理
os.path模块:处理文件路径
os.path.join("/a", "b", "c", "d.txt")
__file__ # 获取当前文件/模块的路径
os模块:
- 系统环境变量
- Linux系统上的文件处理
- 进程处理
os.environ:可以改环境变量
sys:获取传入给程序的外部参数argv,进程的输入输出流sys.stdout,sys.stdin环境信息相关。
import sys
sys.executable #判断程序运行的环境
Python从外部获取的参数为字符串。
# 重定向stdout
_back = sys.stdout
f = open("txt.txt", "w")
sys.stdout = f
print "kkk"
f.close()
sys.platform:查看程序运行在什么平台
subprocess:
Popen:用来创建子进程
网络相关:
- urllib
- httplib
数据处理:
- xml模块
- json模块
六、virtualenv和virtualenvwrapper
- virtualenv
pip install virtualenv
pip freeze
pip freeze | wc -l # 统计安装的模块
virtualenv ENV # 创建一个virtualenv的一个虚拟环境ENV
source ./ENV/bin/activate # 启动ENV
deactivate # 离开virtualenv环境
which python # 查看Python可执行文件的路径
所有安装在系统范围内的包对于virtualenv是可见的,这意味着若将simplejson安装在系统Python目录中,它会自动提供给所有的virtualenv使用。这种行为可以被更改,在创建virtualenv时增加--no-site-packages
选项的virtualenv就不会读取系统包,例如:virtualenv ENV --no-site-package
。
- virtualenvwrapper
建立在virtualenv上的工具,通过它可以方便的创建/激活/管理/销毁虚拟环境。
workon ENV # 启用ENV
workon # 列出所有虚拟环境
mkvirtualenv ENV # 创建
workon ENV
rmvirtualenv ENV
七、回顾
- 当应用计数为0时,GC回收变量占用的 内存;
del 变量名
:删除变量,释放占用的内存;
is
语句:用来判断两个变量是不是指向同一个内存对象; - 声明编码格式,支持中文
# coding:utf8 或
# -*- coding:utf8 -*- # 一般放在第二行
#!/usr/bin/python # 放在第一行
- built-in类型
- 数值类型
- 布尔类型
- 序列类型
- 集合类型
- 映射类型
- python模块
Python程序由多个模块文件组成,模块是程序执行的唯一入口;模块是可以被其他模块导入,模块文件为文件名。
- 模块执行最简单方法
python [module].py
#! /usr/bin/python # 当前python解释器
- 也可以使用./module.py来调用
模块中定义了什么:
- 变量[模块级别]
- 函数的定义
- 类的定义
- 程序的实际调用逻辑
- 数据类型
使用弱类型
- built-in类型
- 自定义的类型(类,integer)
变量名字大小写敏感,以下划线、数字、字母命名,以下划线、字母开头;
支持多个变量的同时定义,简化代码编写:
a, b = 'django', 2
数据类型:
- 整型:32/64 bit,在python3已移除
- 长整型:没有长度限制,受内存大小限制
- 浮点型
- 复数类型
/ # 普通除法,两个均为整数时,四舍五入;为浮点数时,结果为浮点数;
// # 地板除,只保留整数部分
空列表、空元组、空字符串、0均表示False
对象三要素:
- identity(身份),对应于内存地址,不可修改
- type(类型),不可修改
- value(值),immutable不可修改和mutable可修改
list | tuple | string正负下标表示:
- 正:0,1,2,...,n-1
- 负:-n,-n-1,...,-2,-1
list支持extend操作,支持原地修改
[list].extend([list])
list(), tuple():创建了一个新的序列对象
字符串是不可变序列,任何一点修改都会创建新的字符串对象。每次'+'操作都会生成一个新的字符串对象。
"".join(序列)
拷贝:
- 浅拷贝:list,tuple工厂函数;切片;copy模块的copy函数;
浅拷贝不会生成一个新的 序列,指向同一个列表。 - 深拷贝:生成一个新的序列
import copy
c = copy.deepcopy(a)
Tips:持续更新。。。