Python入门
python主要用途是网页爬虫,大数据分析,人工智能。
变量和数据类型
python中变量就一个变量名,变量名必须是大小写英文、数字和下划线的组合,不能用数字开头。
python中数据类型有:整数、浮点数、字符串、布尔值、空值(None)、List、Tuple、Dic、Set
String字符串
字符串可以用''
,""
,''''''
包含。
如果有需要转译的特殊字符可以使用\
如果一个字符含有多个需要转义的字符,我们可以在字符串前添加前缀r
,表示这个raw字符串,里面的字符不需要转义。r'\(~_~)/'
但是r'...'
不能表示多行字符串也不能包含''
和""
。
多行字符串可以用'''.....'''
表示。
定义文件字符编码在文件头部添加# -*- coding: utf-8 -*-
如果字符串里面还有中文,需要在字符串前添加u
例如:u'中文'
int和float整数和浮点数
python中整数和整数计算结果肯定是整数,浮点数和浮点数计算结果肯定是浮点数。而整数和浮点数计算结果是浮点数。
1 | 1+2 #==>3 |
Boolean布尔类型
python中布尔类型只有True
和False
两种。
布尔运算类型:
1 | True and True # ==> True 与运算 |
list数组
python中list
是中有序的集合,可以随时添加和删除元素。
1 | empty = [] # 一个空list |
list
是有序的集合,可以通过索引(从0开始)访问某个值:
1 | name = ['fynn','echo'] |
添加和删除list
我们可以使用append()
向list
末尾添加值:
1 | name = ['fynn'] |
我们可以使用insert(index,value)
向list
指定位置插入值:
1 | name = ['fynn','echo'] |
我们可以使用pop(index)
删除某个位置的值并获取它:
1 | name = ['fynn','small mouse','echo'] |
如果我们不设置需要删除的位置pop()
会删除list最后一个值
Tuple 元组
tuple(元组)是另外一种有序的列表。tuple一旦创建完毕就不能修改。
1 | name = ('fynn','small mouse','echo') |
‘可变’的tuple
1 | name = ('fynn',['echo']); |
tuple每个值的指向没有改变,元素list本身是可变的。
dict 对象
dict
表示’名字’对应的’成绩’。有花括号{}
包含。
1 | human = {'name':'fynn',age:27} |
dict
特点是查找速度快,无论是10个元素还是10万个查找速度一样,而list
查找速度随着元素增加而逐渐下降。但dict占用内存大。dict
存储的key-value序对是没有顺序的。dict
的key元素是不可变的
Set
set 拥有一系列元素,它和list很像。但set元素没有重复而且是无须的!
1 | name = set(['fynn','echo','fynn']) |
访问set
set是无序集合,我们无法通过索引来访问。我们只能判断某个值是否在set中。
1 | name = set(['fynn','echo']) |
更新set
把一个新元素添加到set中,并删除一个已有元素。
1 | s = set([1,2,3,4]) |
条件判断和循环
python代码使用缩进规则,具有相同缩进的代码被视为代码块。
If
python 中if是最常用的判断方式:
1 | name = 'fynn' |
For
python的 for
循环可以依次把list
或tuple
的每个元素迭代出来
1 | name = ['fynn','echo'] |
除了list
和tuple
。for
还可以迭代dict
,set
While
while循环不会迭代list
或tuple
元素,而是根据表达式判断循环是否结束。
1 | N = 10 |
Break 和 Continue
break
用于提前结束循环,而continue
用于跳过此次循环。
函数
python中定义一个函数要要使用def
语句,依次写出函数名、括号、括号中的参数和冒号,然后在缩进块中编写函数体,函数返回值用return
语句返回。
1 | def hello(name): |
如果没有return
语句,函数执行完毕后结果是None
返回多个值
python中可以返回多个值。在函数代码块内return
语句将需要返回的值用,
分隔就可以了。
1 | import math |
python函数返回多个值其实就是返回一个tuple。
默认参数
python中可以给函数参数设置默认参数,当调用函数没有传参时,函数就会使用设置的默认参数。
1 | def hello(name='world'): |
可变参数
python可以接受任意个参数
1 | def fn(*args): |
python解释器会把传入的一组参数组装成一个tuple,在函数内部,直接把变量args
看成tuple
就可以了。
匿名函数
python中使用lambda
定义匿名函数。python函数有很多限制:
Lambda
函数能接收任意数量的参数但只能函数体只能有一条表达式。- 匿名函数不能直接调用print,因为
lambda
需要一个表达式。 labbda
函数拥有自己的名字空间,且不能访问自有参数列表外或全局名字空间的参数。
1 | sum = lambda arg1,arg2:arg1+arg2; |
切片
获取list
、tuple
一部分元素是个很常见的操作。python提供了快捷的获取方式,称为切片。
1 | name = ['fynn','echo','mouse'] |
name[0,2]
表示从索引0开始取,直到索引3为止,不包含3。
如果只有 :
例如name[:]
则表示从头取到尾。
切片还可以指定第三个参数:
1 | name[::2] # ['fynn','mouse'] |
第三个参数表示每N个取一个,上面name[::2]
会每两个元素取一个,也就是每隔一个取一个。
迭代
python中,如果给定一个list或tuple,我们可以通过for循环来遍历这个list 或tuple。这种遍历我们称为迭代。
for循环可以用在任何可以迭代的对象上:有序集合(list,tuple,str,unicode)、无序集合(set)、无序集合并具有key-value(dict)。
索引迭代
python中迭代永远取出元素本身,而非元素的索引。
对于有序集合,元素是有索引的如果我们想拿到索引就要使用enumerate()
函数
1 | name = ['fynn','echo','mouse'] |
使用enumerate()函数,我们可以在for循环中同时绑定索引index和元素name。
enumerate()函数其实把['fynn','echo',''mouse]
变成:[(0,'fynn'),(1,'echo'),(2,'mouse')]
迭代dict
for循环我们只能拿到dict的key,如果想拿到value。可以使用dict对象中的values()方法,这个方法把dict转换成一个包含所有value的list,这样我们迭代的就是dict的每个value:
1 | human = {'name':'fynn',age: 27} |
在python文档中,dict除了values()方法外,还有一个itervalues()方法。它们两迭代效果完全不一样。
不同之处是:
values()实际是吧dict转换成一个包含value的list,而itervalues()方法不会转换,它会在迭代过程中依次从dict中取value,所以itervalues()会比values()方法节省生成list所需的内存。
迭代dict同时获得key和value
python中dict对象的items()方法会把dict对象转换成包含tuple的list,我们对list迭代就可以同时获得key和value。
1 | human = {'name':'fynn',age: 27} |
items()也有类似的iteritems()方法。
列表生成式
python中我们经常需要生成list,而python提供了生成列表快捷写法。
1 | [x*x for x in range(1,5)] |
把要生成的元素公式放前面,后面跟着for循环,就这样把list创建出来了。
复杂表达式
1 | d = {'fynn':27,'echo':27,'mouse':1} |
字符串可以通过%
进行格式化,用指定的参数代替%s
。字符串join()
方法可以把一个list拼接成一个字符串
条件过滤
列表成式的for循环后面还可以加上if判断
1 | [x*x for x in range(1,5) if x % 2 == 0] |
多层表达式
for循环可以嵌套,因此列表生成式中也可以多层for循环来生成列表
1 | [m+n for m in 'ABC' for n in '123'] |
函数式编程 functional
- 把计算视为函数而非指令
- 纯函数式编程:不需要变量,没有副作用
- 支持高阶函数,代码简洁
高阶函数
能接收函数做参数的函数
1 | def add(x,y,f): |
map()函数
map(fn,list)
是python内置的高阶函数,它接收一个函数 f和一个list,通过把函数 f依次作用在list的每个元素上,得到一个新的list并返回
1 | def f(x): |
map(fn,list)
并不会改变原有list,而是返回一个新list。
reduce()函数
reduce(fn,list,initValue)
函数是python内置高阶函数。
传入reduce的函数fn必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终的结果值。
1 | def f(x,y): |
reduce(fn,list,initValue)
第三个参数做为计算的初始值。
filter函数
filter(fn,list)
是python高阶函数。接收的第一函数 fn和一个list。
函数fn的作用是对每个元素进行判断,返回True或False。filter根据判断结果自动过滤不符合条件的元素,返回由符合条件元素组成的新list。
1 | def is_odd(x): |
利用filter()可以删除Node或空字符串:
1 | def is_not_empty(s): |
sorted()
sorted(list,fn)
是个python高阶函数,它可以对list进行又由低到高排序。它还可以接收一个函数,自定义排序规则。
比较函数fn接收两个参数x,y。如果x应该排在y前面返回-1,如果x应该排在y后面,返回1。如果x和y相等,返回0。
1 | def reversed_cmp(x,y): |
闭包
内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
1 | def calc_sum(lst): |
decorator 装饰器
python的decorator本质上是一个高阶函数,它接收一个函数作为参数,然后返回一个函数。
通过decorator可以将通用代码抽了出来放在一起。
1 | def log(f): |
加入有函数会传入多个参数可以使用python的*args
和**kw
保证任意个数的参数总是能正常调用:
1 | def log(f): |
带参数的decorator
装饰器函数也是可以接收参数的。不同的函数使用装饰器传递不同参数可以得到各自想要的结果。
1 | def log(prefix): |
完善decorator
decorator函数会改变原函数一些基础信息,例如函数名(fn.name)。为了不改变原函数基础信息需要在decorator中做些操作。
1 | def log(f): |
偏函数
如果函数有多个参数时,调用者就需要传多个参数。如果减少参数个数,就可以简化调用者的负担。
python中提供一个 functools.partial
工具方法给函数设置传递的默认参数简化函数的调用 。
1 | import functools |
Class类
类(Class)用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。
定义一个person
类:
1 | class Person(object): |
按照python的编程习惯,类名以大写字母开头,紧接是(object)
表示是从哪个类继承下来的。创建实例使用类名+()
初始化实例属性
Class具有一个特殊的__init__()
方法,当创建实例时,__init__()
方法被自动调用,我们就能在此为每隔实例都统一加上一下属性:
1 | class Person(object): |
__init__()
方法的第一个参数必须是self
。Class的属性方法第一个参数也必须是self
。名字是可以随意取。
创建实例时,就必须要提供除self
以外的参数
访问控制
如果我们不想将某个属性让外部访问,只需将属性设置为__
开头就可以了。
1 | class Person(object): |
只有__双下划线开头__的__age
不能被访问。
如果一个属性是__xx__
的形式定义,它是可以被外部访问的,以__xx__
定义的属性在python的类中被称为特殊属性,有很多预定义的特殊属性可以使用。
以__单下划线开头__的属性_xxx
虽然也可以被外部访问,但是,按照习惯,它们不应该被外部访问。
创建类属性
类是模板,而实例则是根据类创建的对象。
实例属性每隔实例各自拥有,互相独立,而__类属性有且只有一份__。
1 | class Person(object): |
类属性和实例属性
类属性会导致所有实例访问到的类属性受到影响。如果某个实例没有某个属性,而类拥有这个属性,则实例会取到类属性。
定义类方法
和属性类似,方法也分__实例方法__和__类方法__。
1 | class Person(object): |
通过标记一个@classmethod
,该方法将绑定到Person
类上,而非类的实例。
类继承
如果已经定义了Person
类,需要定义新的Student
和Teacher
类时,可以直接从Person
类继承。
1 | class Person(object): |
一定要用super(Student, self).__init__(name, gender)
去初始化父类,否则继承自Person
的Student
将没有name
和gender
。
函数super(Student, self)
将返回当前类继承的父类,即Person
然后调用__init__()
方法。注意__self参数已在super()中传入,在__init__()中将隐式传递,不能写。__
类型判断和获取对象信息
函数isinstance()
可以判断一个变量的类型,可以在python内置的数据类型如:str、list、dict
,也可以用在我们自定义的类。
1 | class Person(object): |
type()
函数获取变量的类型
1 | print type(123) # <type 'init'> |
dir()
函数获取变量的所有属性
1 | print dir(s) # ['__class__','name','gender',...] |
getarr()
获取已知属性的值,setattr()
设置属性值
1 | getattr(s,'name') #获取 name属性 |
特殊方法
python的某些函数或操作符自动会调用的方法。
__str__()
字符串序列化。如果把一个类实例变成__str__,就需要实现特殊方法__str__()
1 | class Person(object): |
__repr__()
因为 Python 定义了__str__()和__repr__()两种方法,str()用于显示给用户,而__repr__()用于显示给开发人员。
__cmp__()
对 int、str 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 __cmp__()
1 | class Student(object): |
上述 Student 类实现了__cmp__()方法,__cmp__用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。
1 | 'Tim', 99), Student('Bob', 88), Student('Alice', 77)] L = [Student( |
注意: 如果list不仅仅包含 Student 类,则 cmp 可能会报错
__len__()
如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。
要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。
例如,我们写一个 Students 类,把名字传进去:
1 | class Students(object): |
只要正确实现了__len__()方法,就可以用len()函数返回Students实例的“长度”:
1 | 'Bob', 'Alice', 'Tim') ss = Students( |
@property
添加对属性访问的控制。在实际开发中我们需要对实例属性赋值取值做个验证。单独写调用属性方法很麻烦,python提供了 属性装饰器@property
可以解决这个问题。
1 | class Student(object): |
注意: 第一个score(self)是get方法,用@property装饰,第二个score(self, score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。
slots
由于Python是动态语言,任何实例在运行期都可以动态地添加属性。
如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。
1 | class Student(object): |
__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。
call()
一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。
我们把 Person 类变成一个可调用对象:
1 | class Person(object): |
模块
python中一个文件就是一个模块,导入模块使用import modelName
。
python中一个文件夹作为一个包(文件夹内必须有__init__.py
文件)。
具体的模块引用路径应该是: import packageName.modelName
from…import
python的from
语句让你从模块中导入一个指定的部分到当前命名空间下。
1 | from modelName import name1[,name2,name3] |
可以给导入的指定函数起别名
1 | from modelName import name1 as aliasName |
I/O
python提供了直接操作文件的方法,只有有打开文件,读取文件,写文件。
打开文件 open()
1 | file object = open(file_name, [, access_mode][, buffering]) |
- file_name: 需要访问的文件名称字符串值
- access_mode: 打开文件方式:只读,写入,追加等
- buffering: 如果buffering的值被设为0,就不会有寄存。如果buffering的值取1,访问文件时会寄存行。如果将buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
1 | 模式 描述 |
close 函数
File对象的close()方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。当一个文件对象的引用被重新指定给另一个文件时,Python会关闭之前的文件。语法为:
1 | # 打开一个文件 |
read函数
read()方法从一个打开的文件中读取一个字符串
1 | # 打开一个文件 |
write函数
Write()方法可将任何字符串写入一个打开的文件。Write()方法不在字符串的结尾不添加换行符(‘\n’)。
1 | # 打开一个文件 |
File对象的属性
一个文件被打开后,你有一个file对象,你可以得到有关该文件的各种信息。
- file.closed 返回true如果文件已被关闭,否则返回false。
- file.mode 返回被打开文件的访问模式。
- file.name 返回文件的名称。
- file.softspace 如果用print输出后,必须跟一个空格符,则返回false。否则返回true。
venv
python默认会将包安装到系统路径上(类似NPM的全局安装),每个项目依赖的包会指向全局的。但在项目中不同的项目我们依赖的同一个包可能版本要求不一样。这样情况下我们就需要使用虚拟环境。
Python3.6以上推荐使用官方的venv
模块。
Python 3.3 and 3.4推荐使用pyvenv
。
创建虚拟环境
在项目跟目录下执行:
1 | python -m venv virtualName |
在跟目录下会有以你刚设置的virtualName
名字的文件夹:
1 | | virtualName |
启动脚本
不同平台启动虚拟环境脚本:
平台 | 脚本类型 | 启动虚拟环境命令 |
---|---|---|
Posix | bash/zsh | $ source |
Posix | fish | $ . |
Posix | csh/tcsh | $ source |
Windows | cmd.exe | C:> |
Windows | PowerShell | PS C:> |
退出虚拟环境
在虚拟环境下执行 deactivate
。
导出/安装依赖包
导出依赖包在到指定文件夹,虚拟环境下执行
1 | pip freeze > requirements.txt |
从指定文件夹安装项目依赖包,在虚拟环境下执行:
1 | pip install -r requirements.txt |
作者: Fynn
链接: https://fynn90.github.io/2017/11/06/python%E5%85%A5%E9%97%A8/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可