Python 基础
Python 基础知识
函数集合
zip(list1, list2): 将list1, list2合并成一个l新的list并返回
dict.popitem(): 返回最后一个键值对并删除
dict.items(): 以序列的形式返回键值对
dict.values(): 你懂的
assert condtion, [string]: 如果condition为True则直接中断程序, 并输出提示信息string
a = [(x, y) for x in range(0,10) for y in range(1,11)]: 此列表解析式中有两个for
循环, 左侧的for循环中嵌套右边的for循环
相当于:
a = []
for x in range(0, 10):
for y in range(1, 11):
a.append((x, y))
def func(args):
"""
如果函数的具体实现并没有确认下来, 可是在这里直接使用字符串充当文档注释
也可是使用pass关键字
"""
注: 在为程序写注释时可以使用#
同时也可以使用字符串充当文档注释, 在函数中写文档字符串, 可以通过funcname.__doc__
获取信息, 也可以在help(funcname)中显示
chr(int): 返回int对应的ASCII
ord(char): 相反
Python中的函数的位置参数都是可以指明变量名赋值的
默认参数是在不填写时使用默认值的参数
在函数的参数列表中使用在一个形参之前使用*号表示此变量会成为一个tuple容器来收集参数
如果想要成为一个可以收集关键字参数的变量, 需要使用两个*号将其保存到dict容器中在给有可变长度的参数的函数传递参数时, 使用 * 号表示拆tuple容器, 而两个*号表示拆dict容器
使用的内置函数:
globals(): 返回全局变量的dict, 用户定义的所有的全局变量都放在一个dict中
建议: 在函数中如果要访问一个全局变量, 使用global()["arg_name"]来访问
也可以使用global arg_name = value; 达到一样的效果
在函数中有定义一个函数, 子函数想要访问父函数中的变量, 建议使用nonlocal指明
语法使用建议
- 优先使用import module语句, 防止命令冲突
- 在函数中尽量不要使用全局变量
- 尽量使用try-except, 有使用使用它代替if-elif-else,
"直接去做, 有问题再处理, 而不是预先做大量的检查"
类与对象
-
定义一个类的实例:
class Person: '类中的每一个方法都是需要传递一个self参数' def set_name(self, name): self.name = name; def get_name(self): return self.name def greet(self): print("Hello, world! I'm {}.".format(self.name)) """ 方法的调用可以: foo = Person() foo.set_name("JC") 或者 foo = Person() Person.set_name(foo, "JC") """
-
为了封装对象的属性, 在定义变量名时以"__"开头即可
实质上: Python解释器会对类中所有的双下划线打头的名称转换成"一条下划线加上类名后面再跟上我们定义的以双下划线开头的那个名称(包括下划线)" -
在类中定义一个变量是归该类所产生的所有的对象所共有的, 类似与Java中的(static修饰符的作用)
-
判断子类与父类(类也是一个特殊的对象)
issubclass(SonClass, FatherClass) ---> True issubclass(FatherClass, SonClass) ---> False
-
查看一个类的父类(类也是一个特殊的对象)
'访问__base__元素和__bases__' SonClass.__base__ 和 SonClass.__bases__
-
判断一个对象是否一个指定类的实例
s = OpenObject() isisntance(s, OpenObject)
-
在类定义时可以在类名之后的括号中添加指定的父类(支持多继承),
如果出现了相同名称的变量则先继承的覆盖后继承的 -
对对象属性的访问的函数
1. hasattr(object, 'attribute'): 如果存在返回True 2. getattr(object, 'attribute', None): 获取对象的属值,<br> 注意: 是直接访问属性而不是调用方法setter与getter 3. setattr(object, 'attribute', value): 为属性设置值 4. callable(value): 如果value为()|{}|None|0则返回False
-
异常处理语句
try:
'可能发生异常的代码块'
except Exception|ZeroDivisionError... as e:
'处理异常'
except OtherEx:
'可以有多个except'
else:
'如果没有没有异常的代码段'
finally:
'不管有没有报异常都会执行的代码'
-
在Python中的__init__方法应该先初始化父类
调用super().init(), 其中super()函数返回一个super
对象, 该对象可以检测到当前类的所有的父类, 在父类中找到__init__函数, 没有找到就AttributeError异常 -
Python可以为对象动态的添加属性
Python中常用的函数
- map(func, [list]): 对序列中每个元素都执行func函数, 并返回一个迭代器, 在for语句中可以迭代出来
- lamba函数: 类型于C语言中宏定义, 可以快速创建单行的函数, e.g lambda x: x * 2
- 不导入math(在math中有math.pi, math.e, math.sin, math.asin等)模块, 在Python内置模块中已经含有了pow, max, min, round, abs等函数
- 自带的随机数生成函数:
1. random.choice(list): 从指定的list中随机选出元素
2. random.randrange(start, stop, step): 从start开始, 步长为step, 终止为stop构成的序列中随机选出一个数
3. random.random(): 0-1
4. random.shuffle(list): 洗牌
5. random.uniform(x, y): 生成的随机数在[x, y)的范围
Python中的装饰符
- 修饰器函数是要至少套一个函数的, 以后调用被装饰器修饰的函数调用的就是装饰器的函数, 并且装饰器函数在加载时就是被执行
- return funA(funB(funC))
- 遇到@修饰的就会读取下一行, 并作为参数传入到修饰符对应的函数中, 当结尾之后就会执行函数, 返回的结果会将原来最有被修饰的func标签执行返回的那个对象的(地址)
- Python中属性是方法的变种, 使用@property(property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值)修饰一个方法, 则那个方法就会相当于有了一个在Java中的get方法, 只不过在访问法的使用不是通过get而是通过访问属性的形式得来的, 为了有配对的setter, 定义一个与@property同名的方法, 含有两个参数, self与value, 使用@funcname.setter修饰该方法即可, 在使用obj.field = somevalue时就会自动调用这段函数, 来处理一些逻辑而用户无需改变之前的代码, 达到简介并且减少对源代码的修改的目的, @field.deleter(如果想要删除一个属性话), 总的来说在Python中get和set应该替换为使用修饰器
![](/Users/air/Macro/MegaChen/Study/ProgramOfStudy/Languages/Python/Notes/Pictures/Screen Shot 2018-06-17 at 23.09.45.png)
修饰的过程就是对应的func标签所指向的对象(地址, 代码逻辑)对应关系变化的过程, 指向的是在装饰函数中返回值, 如果有@xxx, 嵌套使用
- 一般在装饰器函数中定义的闭包, 需要参数的话, 使用*args, 以及**kw, 目的是为了兼容原来别修饰的函数
- 带定义带参数的修饰器函数需要有二层嵌套, 第一层定义参数为func的函数, 第二层定义wrapper函数
python中的魔法方法
- __init__: 在对象被创建时自动调用
- __del__: 析构函数, 在对象被回收前调用
注意点
1. 所有的变量都是在一个指定的命名空间中的, 而命令空间就是一个dict容器
2. 在类中线性定义的任何方法和属性都是只有一份的, 类似于Java中的static修饰符
3. 定义一个类的属性时, 要想其对每一个该类所创建的对象都是独立的, 需要将属性的赋值操作放在一个方法中, 在使用该对象时如果需要使用该属性, 就必须先执行该方法让该对象有该属性, 否则会报找不到属性的错误
4. 因为Python中的变量没有类型, 所以在使用一个变量时应该先为该变量赋值, 如: x = "", y = 0, li = [], dic = {}, se = set()
5. 在python交互式环境中没有使用print打印出来但是确实输出到了控制台上, 实际上调用的是对象的__repr__方法, 显示的Python解释器处理的字符串, 而使用print调用的是__str__函数
6. 很多标准库函数返回的是迭代器
7. 自己实现一个可以迭代的对象时, 在__next__方法中需要在迭代末尾条件成立时raise StopIteration()异常结束迭代
生成器
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。
当 Python 将 gen_fn 编译为字节码时,它会看到 yield 语句,然后知道 gen_fn 是个生成器函数,而不是普通函数。它会设置一个标志来记住这个事实
当你调用一个生成器函数时,Python 会看到生成器标志,实际上并不运行该函数,而是创建一个生成器(generator)
Python 生成器封装了一个堆栈帧和一个对生成器函数代码的引用,在这里就是对 gen_fn 函数体的引用
返回生成器可以调用send(None)使用生成器
Python高级编程
- 在用户的家目录下创建一个.pythonstartup文件, 在export PYTHONSTARTUP=~/.pythonstartup, 使用python进入到交互式程序时就会读取该文件, 使得可以使用tab进行自动提示
- python中有一个distutils的模块, 用于发布程序, 但是不能解决包之间的依赖关系, 所以就诞生了setuptools工具, 要安装settools工具, 需要下载ez_setup.py(这就是ease_intall), 接着使用python ez_setup.py setuptools安装setuptools程序就会有一个easy_install命令, 以后使用ease_install(即为setuptools的命令程序)安装第三方的模块即可
不过一般在安装python时已经内置了easy_install命令和pip, 如果没有pip(就是要一个拥有执行全向的python脚本)命令则使用easy_install pip(因为easy_install就是用来下载python脚本的, 所以可以下载pip)
pip是easy_install的升级版, easy_install不能下载的可能pip可以下载
-
动态获取PyCodeObject对象
source = open('filename.py', 'w').read() co = compile(source, 'filename.py', 'exec')
-
每次对序列进行循环处理时尽量使用列表解析式, 因为快
-
获取当前的frame信息
sys._getframe(): 返回一个frame对象
-
导入一个python文件时, python虚拟机会执行其中的代码, 执行的代码的存储空间实在那个要导入的模块的命名空间中, 所以我们想要访问时就需要使用模块名来访问
[importtest.py] import os import sys import math import math import time import numpy import scipy [test.py] import importtest # Use the os module imported from importtest module print('The sysstem path is', importtest.sys.path)
-
凡是要安装python的第三方库或者工具, 使用pip3 install
1. 显示某一特定目录下的所有文件, os.path.listdir(dirname)
2. 拆分文件名和扩展名, os.splitext(name)
3. python没有静态类型, 这一弊端在初始化时可能用户会传入意料之外的值, 这是可以定义一个函数
专门用来检验类型, 如传入了"name", 该函数就会调用type("name") is str, 来判断是否是str类型
4. print函数调用的是对象的__str__方法
- 许多内置的Python模块在Python启动的时候已经加载到内存中了, 只是对外部是不可见的, 主要导入import sys, 通过sys.modules这个全局的模块池就可以不直接到如类似于time, pprint而通过sys.modules['pprint'].pprint来获取模块中的服务
- import imp, 使用imp.reload可以重新到如模块, 就是重新执行模块中的内容, 通过reload可以动态修改py文件, 但是不会删除内容, 只能添加内容, 重新都如不会重新创建之前创建的实例
- Cython使用
1. 通过pip3 install cython安装cython, cython不是一门语言, 而是一个工具
2. 在编译cython的.pyx文件, 需要编写setup.py文件
3. 在Ternimal中键入, python3 setup.py build_ext -i即可
sys模块
argv:命令行参数List,第一个元素是程序本身路径
builtin_module_names:Python解释器导入的模块列表
modules.keys():返回所有已经导入的模块列表
exc_info():获取当前正在处理的异常类
exc_type、exc_value、exc_traceback:当前处理的异常详细信息
executable:python解释程序路径
exit(n):退出程序,正常退出时exit(0)
getwindowsversion():获取Windows的版本
hexversion:获取Python解释程序的版本值,16进制格式如:0x020403F0
version:获取Python解释程序的版本信息
maxint:最大的Int值
maxunicode:最大的Unicode值
modules:返回系统导入的模块字段,key是模块名,value是模块
path:返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
platform:返回操作系统平台名称
os模块(封装了与文件系统有关的操作)
os.remove(path) 或 os.unlink(path) :删除指定路径的文件。路径可以是全名,也可以是当前工作目录下的路径。
os.removedirs:删除文件,并删除中间路径中的空文件夹
os.chdir(path):将当前工作目录改变为指定的路径
os.getcwd():返回当前的工作目录
os.curdir:表示当前目录的符号
os.rename(old, new):重命名文件
os.renames(old, new):重命名文件,如果中间路径的文件夹不存在,则创建文件夹
os.listdir(path):返回给定目录下的所有文件夹和文件名,不包括 '.' 和 '..' 以及子文件夹下的目录。('.' 和 '..' 分别指当前目录和父目录)
os.mkdir(name):产生新文件夹
os.rmdir(name): 删除目录
os.makedirs(name):产生新文件夹,如果中间路径的文件夹不存在,则创建文件夹
os.islink(path):返回是否是快捷方式
os.linesep
os.sep
os.path模块(涉及到路径一定要想到os.path模块)
os.path.isfile(path) :检测一个路径是否为普通文件
os.path.isdir(path):检测一个路径是否为文件夹
os.path.exists(path):检测路径是否存在
os.path.isabs(path):检测路径是否为绝对路径
split 和 join
os.path.split(path):拆分一个路径为 (head, tail) 两部分
os.path.join(a, *p):使用系统的路径分隔符,将各个部分合成一个路径
os.path.abspath():返回路径的绝对路径
os.path.dirname(path):返回路径中的文件夹部分
os.path.basename(path):返回路径中的文件部分
os.path.splitext(path):将路径与扩展名分开
os.path.expanduser(path):展开 '~' 和 '~user'
normcase(path):转换路径中的间隔符
normpath(path):转换路径为系统可识别的路径
realpath(path):转换路径为绝对路径
re模块
re.match(patterstr, string)
re.search(patterstr, string)
两者都寻找第一个匹配成功的部分,成功则返回一个 match 对象,不成功则返回 None,不同之处在于 re.match 只匹配字符串的开头部分,而 re.search 匹配的则是整个字符串中的子串。
datetime模块(主要是可以计算)
- 含有3个主要的类: date(之后年月日星期), time(只有时分秒), datetime(都有)
date对象的方法:
(1) obj.today()
(2) obj1 - obj2: 返回timedelta(对象, 维护着时间数据), 支持减法操作
(3) print d1.strftime('%A, %m/%d/%y') 格式化输出
time对象的方法:
obj.strftime("%a, %HH%MM%ss")
datetime对象的方法:
(1) obj.now()
(2) obj.strptime('format')
常见标准库
常用的标准库
re 正则表达式
copy 复制
math, cmath 数学
decimal, fraction
sqlite3 数据库
os, os.path 文件系统
gzip, bz2, zipfile, tarfile 压缩文件
csv, netrc 各种文件格式
xml
htmllib
ftplib, socket
cmd 命令行
pdb
profile, cProfile, timeit
collections, heapq, bisect 数据结构
mmap
threading, Queue 并行
multiprocessing
subprocess
pickle, cPickle
struct
面向对象
super(cls, instance) # 在Python3中直接是super()
super函数的实现大致为:
# 所以准确的来说, super不是返回父类类型对象, 而是返回cls中的__mro__列表中的下一项, 封装为super对象
def super(cls, instance): # 在Python3中调用的super(__class__)
return super(cls.__mro__[cls.__mro__.index(cls) + 1]);
# 之后如果调用super().__init__()方法, 在该__init__()中根据super获取的类型对象的__init__方法进行初始化
extra
In [37]: testDict = {i : i*i for i in range(5)}
In [38]: testSet = { i*2 for i in range(5)}
In [39]: testDict
Out[39]: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
In [40]: testSet
Out[40]: {0, 2, 4, 6, 8}
翻转列表本身
In [49]: testList = [1, 3, 5]
In [50]: testList.reverse()
In [51]: testList
Out[51]: [5, 3, 1]
在一个循环中翻转并迭代输出
In [52]: for element in reversed([1,3,5]):
...: print(element)
...:
5
3
1
一行代码翻转字符串
In [53]: "Test Python"[::-1]
Out[53]: 'nohtyP tseT'
file对象
file对象操作
open(文件名,模式,缓冲):模式可以置为(r,w,a,r+,w+等),这些模式本身不会去锁定文件,在同时使用读和写时,要使用seek来移动位置。
close():关闭的作用是置位closed,多次关闭不会引发异常。
flush():将内在缓冲的内容写入文件。
read(n):读入若干字节,无n时,读入全部。
readline(n):读入若干行,n表示读入的最长字节数。
seek(offset,where):where=0从起始位置移动,1从当前位置移动,2从结束位置移动。
tell():文件的当前位置。
truncate(n):截断文件为n个字符,无n表示从当前位置起截断。
write(str):在当前位置写入字符串。
writelines(lines):相当于给lines中的每个字符串调用write函数。
requests模块
- requests.get(), post(), delete(), put()
- res.string(以字符串形式显示), .content(原始内容, 二进制形式), .encoding
pickle模块(类似Java中的序列化)
- pickle.dumps(obj): 将Python对象转为bytes对象
- pickle.loads(string): 将bytes转为对象的Python对象
- pickle.dump(obj, file)
- pickle.load(filep)
json模块
- json.loads(jsonstring): 返回一个dict
- json.dumps(jsonstr): 返回一个str
- json.load
- json.dump
shutil模块(高级文件系统管理)
- .rmtree: rm -rf
- .copy: cp
- .copytree: cp -r
- ...
glob模块
- glob.glob()
发布Python代码
- 创建一个目录
- 将代码放在该目录下
- 在目录下创建setup.py
- 在setup.py文件中
from distutils.core import setup
# setup(**kwrags)
setup(
name = '',
version = '',
author = '',
py_module = [''],
description = '',
url = ''
)
- python setup.py sdist
- 完毕
- 安装 --> python setup.py install
setup.py的命令行
python setup.py sdist: source distribute
python setup.py install: install module
BeautilfulSoup模块
- soup.content, .children(返回一个迭代器), .string(文本内容, 在二层嵌套之内可以使用), .parent, .title..., tag['arr_name'], .descendant递归遍历的迭代器
- .next_sibling 和 .previous_sibling
- parents
- .attrs
对树形结构的文档进行特定的搜索是爬虫抓取过程中最常用的操作。
<h4>find_all()</h4>
find_all(name , attrs , recursive , string , ** kwargs)
<h5>name 参数</h5>
查找所有名字为 name 的tag
fileinput模块(让你迭代所有的行, 他的应用是在命令中执行Python解释器时: Python file.py test.py)
-
fileinput.input(inplace=True): 最重要的函数, 返回一个可以在for中迭代的对象, inplace=True会修改文本内容
-
fileinput.filename
-
fileinput.lineno: 一直增加
-
fileinput.filelineno: 遇到新的文件会归零
-
fileinput.nextfile: 到下一个文件
-
fileinput.close: 关闭
-
支持延迟迭代, 当文件比较大的使用, fileinput.input(filename)
-
文件对象都是可以迭代的, 所以 for line in open(filename): print(line)
``` for line in fileinput.input(filename): dosome about line ```
for line in fileinput.input(inplace=True):
'# {0}'.format(fileinput.filelineno).join(line, '')
heapq模块(主要特征就是实现了堆排序)(实际就是list)
- heap的定义是一个list
- heappush, heappop是函数
- heapify, 将一个list转为由堆特征的list(也就是所谓的heap)
- heapreplace(heap, value): 取出heap中最小的, 并且添加一个value新元素
collections模块(提供了双端队列)
- deque(iterable)
- append
- appendleft
- pop
- popleft
time模块
- localtime(sec): 根据sec返回时间元组, 一般与asctime((tuple))使用显示时间字符串, 时间元组是tuple的子类
- asctime((tuple)): 将时间元组转为字符串, 无参数返回的是当前时间
- mktime(tuple): 转为当地时间float类型的
- sleep(sec): 程序休眠时间
- time(): 返回当前时间的毫秒数
- strptime(): 与asctime相反
- gmtime(): 国际时间
shelve模块(小型的数据库)
- open(filename)
- 对象是一个映射, obj['x'] = [1, 2, 3]
常用函数
- memoryview(btypearray('string', encoding='utf-8')): 返回一个内存查看对象, 拥有类似于指针的功能, 可以查看对象内部的信息, 用于在对字符串进行切片操作时可以将其转为memoryview对象
- zip(): 函数可以拼接两个序列
- frozenset():根据传入的参数创建一个新的不可变集合
- m[start:stop:step]切片
- slice(start, stop, step): 返回一个切片对象, 它就是li[slice]中的slice, 形式是我们经常使用的0:10等
- vars(obj): 调用obj__dict__()函数, 返回本地变量
- ascii(), bin, map(), zip(), filter(), reduce(), max(), min(), sum(), range()
Cython
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext = Extension("fib", sources=["fib.pyx"])
setup(ext_modules=[ext], cmdclass={'build_ext': build_ext})
tkinter模块(GUI)
socket模块
- 服务器端
s = socket.socket()
host = s.gethostname
port = 1234
s.bind((host, port)) # 绑定监听的套接字
s.listen(5) # 最大连接数量
while True:
client, address = s.accept()
c.send(b'Hello world!') # bytes对象
c.close()
s.close()
- 客户端
s = socket.socket()
host = s.gethostname()
port = 1234 # 服务器端的端口
s.connect((host, port))
print(s.recv(port)) # 接受的是bytes
注意
Python中的对对象的访问与赋值的第一步都是先访问对象的__getattribute__, __getattr__, __setattr__, __delattr__, 包括使用了修饰符的函数, 总的来说,
凡是在程序中出现obj.field或者obj.field = something第一步都是调用上述对应的方法
- 为Python添加模块的查找路径可以使用sys.path.append(), 添加PYTHONPATH环境变量
- 序列要实现4个协议, len, getitem, setitem, delitem
建议
- python中可以使用简短的表达就是用简短的表达, 这是Python开发者所希望的
- 使用列表解析式和生成器解析式
- 使用dictobj.get(key, default)和dictobj.setdefault(key, default)
- 使用for循环循环指定次数时会用xrange()减少不必要的浪费, 它不会一下子生成一个大list, 而是一次输出一个
- 尽可能使用in判断序列中有没有指定的元素
- 使用拆包交换两个变量的值, x, y = y, x
- 合并字符串使用join, 因为字符串时不可变的, 使用'+'会造成不必要的浪费, 而是用join(list), 则减少了开销
- 遍历dict使用for key in dict: do some about dict[key]
- 能用一个变量表示True就用一个变量, 不适用==, 让代码简洁
- 在Python3中range就是xrange了
- API需要简单, 易记, 易用
- 有多个参数, 可能导致函数长, 拆分成_xxx等函数, 如果一个类中的方法太多, 考虑增加类
pip使用
- install, uninstall
- pip install -i https://some intalledpkg