PYTHON
Basic
2017.10.24
安装: Mac 版本10.12.6
安装homebrew终端运行
|
|
安装python3
|
|
安装完成之后,在终端运行python3
就进入交互模式,在>>>
之后输入代码,回车之后就直接运行。exit()
退出交互模式。
或使用文本编辑器sublime等。编辑代码,开头加入#!/usr/bin/env python3
并保存为.py后缀的文件。在终端内直接输入文件路径即可执行结果。
mac终端bash 文件运行提示:Permission denied,处理方法:先bash到文件所在位置,运行命令chmod a+x ./filename
基础:输出print()
可以接受多个字符串,逗号会输出成空格;算式可以输出计算结果;输入input()
;输出一些特殊符号时使用\转义符号,\n表示换行,例如:
|
|
还可以用r''
表示’ ‘内部的默认不转义,例如:
|
|
数据类型:整数、浮点、字符串、布尔值(true/false,可以用and、or、not计算)、空值(none,不是0)、变量、常量、列表、元组
复数 z=a+bj
j代表虚数部分,a b皆为浮点型 z.real
实数部分。z.imag
虚数部分。
数字类型间转换:int()
整 float()
浮 complex()
复。注意复数不能直接转化为整和浮点,不过它们可以混合运算,结果为最宽类型(int<float<complex)
type()
返回类型
字符串方法:
|
|
除法:/(结果为浮点型) 地板除://(取整)取余%
字符编码:从ASCII到统一标准的Unicode,以及对Unicode作出简化的UTF-8。python3使用Unicode编码,意味着适用于所有语言,ord()
将字符串显示为其十进制的Unicode编码,chr()
将编码显示为字符串。
在代码前面写# -*- coding: utf-8 -*-
以保证使用UTF-8编码
格式化字符串运算符%:
|
|
%d | 整数占位符 |
---|---|
%s | 字符串 |
%f | 浮点数 |
%x | 十六位进制数 |
Format格式化字符串:eg
|
|
列表list有序集合,和js数组一样,用[ ]定义,用[]获取。len()
获取长度。[-1]
索引为-1获取倒数第一个元素
<seq>+<seq>
连接
<sep>*<整数>
整数次重复
<expr> in <seq>
成员检查
.append()
插入新元素到列表末尾
.pop(i)
删除索引为i的元素,无参数时删除末尾元素,并获取被删除元素。
.insert(i,x)
插入元素x到位置i
.index(x)
x的索引
元组tuple:用()定义,逗号分隔,定义时就需确定其元素组成,元组之所以为元组在于其不可变性,没有类似list这样的append方法,不过也是用[]获取。元组中各个元素随便什么类型。+ * 进行运算
条件判断if python特别的就是不打括号,但要注意冒号和两格缩进,以及else if 缩写成elif
|
|
(age想用input输入但是报错?因为input返回的数据类型是str,用int()
来将字符串类型转化为整数类型)
循环之for in 迭代list或tuple中的每一个元素,计数循环。例如:
|
|
如何计算1-100的整数之和?tips:range(101)
可以生成1到100的整数序列,list()
可以将他转位list:
|
|
循环之while 同理
|
|
字典dict dictionary存储着键值对key-value,用{ }定义感觉比较像json?操作:
|
|
方法:
|
|
注意dict的key必须为不可变对象,所以list不能作为key
字典例子:词频统计
|
|
set :set是一组key的无序无重复合集,不存储value,创建set时需要list作为输入
|
|
.remove(key)
.add(key)
方法为set移除/添加key
2017.10.26
help()
如果输入的是python中有的对应的函数/操作,进入帮助界面,按q
退出
python的内置函数们 参考链接:https://docs.python.org/3/library/functions.html#help
ads(x)
return the absolute value of x,绝对值
bin(x)
return the binary string of x and preside with 0b, 将十进制数转换为二进制且以‘0b’开头
bool(x)
returnTrue
if x true, when x is omitted or false returnFalse
前面提到的chr()
和ord()
字符串<->编码
filter(function,iterable)
,返回iterable中所有function返回true的元素
isinstance(obj, class_or_tuple, /)
Return whether an object is an instance of a class or of a subclass thereof. A tuple, as in isinstance(x, (A, B, ...))
, may be given as the target to
check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)
or …`` etc.
pow(x,y)
x的y次幂
……太多了待学习待补充
定义函数
|
|
从保存的py.py文件中导入其内部定义的函数myfunc( ):
|
|
函数可以同时返回多个值,但实际上是一个tuple
####练习:
请定义一个函数quadratic(a, b, c)
,接收3个参数,返回一元二次方程:ax2 + bx + c = 0的两个解。
|
|
位置参数可以说是必选参数吧,要放在最前面的。
但函数有多个函数时,可以将后几个参数设置为默认参数以简化调用,必选参数须在前,但参数不是默认值时在调用时按顺序输入即可,不按顺序时须指明 参数名=“ ”。默认参数必须是不可变对象。
可变参数 可传入个数不定的参数,在参数名前面加*
就可以,随便你传入几个参数,会默认变成一个tuple。如果你已经有了一个tuple或者list,在前面加 *
可以让其中每一个元素变为可变参数。例如:
关键字参数 前面**
在函数内部自动形成一个dict。关键字参数可以多个,也可以直接穿入dict。例如:
|
|
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city
和job
作为关键字参数。这种方式定义的函数如下:
|
|
和关键字参数**kw
不同,命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数。
2017.10.28
递归:函数内部调用本身即递归。递归次数过多时会导致栈溢出,解决办法是尾递归优化:返回一个函数而不是返回一个包含函数的算式。例如计算n的阶乘,优化前:
|
|
return
中每调用一次nj就往下推一个栈,一直到n=1时才能开始一次往外推出并计算。优化:
|
|
这个结构就是平行的,每一次return都不需要推栈。反正尽管这么说实际上的代码也还不能做到尾优化,就一个思路看看吧。
一些好使的操作符,很js蛮像的(为什么?其实大家语言都像,但我只学过js,hhhh)
切片slice[:] 含前不含后,0可省略,负数索引倒数。
|
|
tuple和字符串同样可以使用以上操作并返回自身切片
迭代: for…in… python中迭代不要求数据类型,只要求是可迭代对象,如何判断可迭代对象:
|
|
list、dict、string均可迭代。对于dict而言,默认对key进行迭代,若要value使用dict.values()
若同时要键和值dict.items()
。
|
|
列表生成式: [ … for… in…… ]:直接看例子吧:
|
|
生成器 generator:和列表生成式用法相同只需将[ ]换成( )。 generator是为了节约内存而存在,它不像列表生成式一样生成完整的列表,它只是保存算法,可以一边循环一边计算,需要多少就计算多少。next()
一次计算一次,直到超出最后一个元素时抛出StopIteration
的错误。
generator是可迭代对象,事实上一般使用时也是用for 循环。
还有一种方法:在函数中包含yield来定义generator,以打印斐波那契数列为例:
|
|
同步赋值语句 :x,y=y,x
交换x,y的值。
每次调用next()
从上一次停止的位置开始到下一个yield
结束!
练习:打印杨辉三角
|
|
迭代器iterator,前面说的list,string,tuple,generator都是可迭代对象,但只有可以使用next()
的generator是迭代器,其他的可迭代对象通过使用iter()
变成迭代器。
2017.10.30
变量可以指向一个函数:
|
|
高阶函数:接收了另一个函数作为参数的函数
|
|
map reduce
map(函数,Iterable)
对Iterable的每一个元素执行函数并返回一个Iterator,通常会再用list()
处理一哈结果。
reduce(function,Iterable)
对Iterable执行函数后,用得到的结果和下一个元素执行下一次函数,是一个累加器吧! 一般返回单个值
给了个例子,自己写int函数的:
|
|
练习:
利用map()
函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT']
,输出:['Adam', 'Lisa', 'Bart']
:
|
|
请编写一个prod()
函数,可以接受一个list并利用reduce()
求积:
|
|
利用map
和reduce
编写一个str2float
函数,把字符串'123.456'
转换成浮点数123.456
:
|
|
还有一个别人的思路,比我的简洁明了多了!!看看别人看看你!
|
|
filter :过滤器filter(function,Iterable)
留下function返true的元素
例子:请打印1000以内的素数
|
|
练习:回数是指从左向右读和从右向左读都是一样的数,例如12321
,909
。请利用filter()
滤掉非回数:
我想到的筛选方法是反转字符串,相等即可,最简单slice方法,步长为-1,直接反转
|
|
2017.11.02
排序 sorted :sorted()
函数可以直接接受一个list对其排序(由小到大),但也可以同时接受一个key
函数,对list中的每一个元素按key
返回的结果进行排序(sorted是映射函数,返回的排序list中还是原始的值哦,不是key处理过的)sorted(list,key:function)
对字符串排序是根据ASCII,所以大写字母都会比小写字母靠前,使用key=str.lower
忽略大小写。
传入第三个参数reverse=True
进行反向排序
练习:假设我们用一组tuple表示学生名字和成绩:
|
|
请用sorted()
对上述列表分别按名字排序:
|
|
返回函数 在函数内部定义了一个函数并且返回这个函数,则形成一个闭包,类似js的,重点不在于调用函数,而在于使用其母环境
匿名函数lambda:
|
|
装饰器 :十一月二号 看不懂装饰器,明天再来看一定能懂,今天先不看,计划通。
十一月21号我才重新看,我反思:相当于给函数加一个外包装,在通过@该定义下调用函数,可以实现打印函数日志之类的功能。
首先,函数是一个对象/函数内部可以定义函数。装饰器一个以另一个函数为参数的函数,在装饰器内部定义一个包装函数,包装函数里面写要在调用函数qian/后执行的操作及函数调用。定义完包装函数,最后装饰器return这个包装函数。使用时@装饰器然后调用函数即可。可以给包装函数传参数,但是如果要给
|
|
上面这段运行结果如下你体会一噶
|
|
关于装饰器的参数问题,我比较奇怪,是@log的时候就传参且调用log了嘛?,然后修改代码如下:
|
|
结果变为: ——clearly 是的!
|
|
就这教程,写的特好!看完就得会!http://www.wklken.me/posts/2013/07/19/python-translate-decorator.html 不过这个教程是用python2.4版本演示的,练习时用3.0注意print的语法
偏函数partial 是functools中的一个函数 functools.partial()
用来给一些内置函数设定默认参数,使之形成新的函数直接调用。例如,设置默认按照二进制转换整数:
|
|
异常处理 try / except
先尝试try
中的语句,若无异常,直接跳到try except
之后的语句,若出现异常则在except
中找对应的错误类型进行操作,还可以使用else
(无异常执行else)和finally
(不管有无异常,最后都执行finally)语句
例如一个除法:
|
|
TypeError: unsupported operand type(s) for /: 'str' and 'str'
input获取的事str 不能运算
ValueError: invalid literal for int() with base 10: ''
当未input时
ZeroDivisionError: division by zero
除数为0、
Sytax Error
非有效python表达式
处理后:
|
|
异常有那么多,不过它们都是BaseException
还有raise
,当他不带参数,就会把当前错误向上抛
调试
assert
断言:
|
|
logging
pdb.set_trace()
设置断点,pdb调试时p
查看变量c
继续运行
单元测试
测试一套完整功能 一个示范
|
|
模块 Module
一个.py文件就是一个模块,里面可以存放写好的函数/参数等,使用时直接引用,不同模块之间的函数不用担心重名。module上面有顶package,包可以一层层的下来,只要同一个包里module不重名就可以,包.包…….py
例如我在prapy.pyz这个文件里写了一个函数叫pra,我在另一个py文件里要用它:
|
|
顺便解释一下if__name__=='__main__':
,通常会放到代码最后,因为在运行本模块时,python解释器会自动把一个特殊变量__name__
置为__main__
,而如果该模块是被导入到其他地方使用,该判断就会失败。也就是说我们在用命令行工具直接打开该模块时它会运行该判断下面的额外语句但当被引入其他模块时就不会,所以可以用来测试运行~
turtle库,图形绘制
绘制python蟒蛇
|
|
一些turtle的方法:
|
|
例子:使用turtle和递归思想画tree:
|
|
绘制中:
再一个例子: 采用 turtle 库并使用函数封装绘制七段数码管,显示当前系统日期和时间。ipo如下:
输入:当前日期的数字形式
处理:根据每个数字绘制七段数码管表示
输出:绘制当前日期的七段数码管表示
效果:
|
|
math库和random库的使用
一个例子:蒙特拉洛法计算pi值。
|
|
DARTS到2的30次方数量级上就基本精确了
random库的一些方法
|
|
面向对象的编程
我理解的面向对象:程序里面是一个个的对象,每个对象里面包含其数据属性方法函数,而对象之间又可以互相作用(传递消息、处理),这样的过程完成一个程序的工作。而与之相对的面向程序的编程就是比较流程化的workflow,顺序执行命令的感觉
封装 继承 多态
类 class 和实例 Instance
|
|
初始化:构造函数__init__
可接受int str float (两个下划线)
删除:析构函数__del__
类的属性和方法。
e.g.: 学生成绩计算 给出信息 找出gpa最高的学生
|
|
面向对象的编程 与类息息相关
特点之 封装 多态(对象怎样回应消息——同一函数启用不同方法,⏰灵活性)。继承(借用另一个类的方法,避免操作重复,提升代码的复用程度)
访问限制
按照以上方法,可以在外部访问并修改实例的参数的值,为了起到保护作用,可以在命名时在前面添加两个下划线 name
变为__name
就成为了私有变量,在外部不可以访问,若要取得其值可以在内部定义getName
方法
继承与多态
前面讲过在定义类时可以同时定义(父类名),该类自动拥有父类的所有功能,可以直接和本类的功能一样调用,此为继承。
如果在子类中重新定义了新的和父类相同的方法,调用时会自动调用子类中新定义的,此为多态。同时,我们在定义类时相当于是新定义了一种类型,其所有实例都是这种类型。子类的类型即是子类,也是父类。一个应用:
|
|
获取对象信息
type()
返回参数的的Class类型12345type(123)==type(456) //Truetype('abc')==str //Truetype(abs) //<type 'builtin_function_or_method'>
isinstance()
方便检测有继承关系的类型123456789#有如下继承关系 object->Animal->Dog->Huskya=Animal()b=Dog()c=Husky()isinstance(c,Husky) //Trueisinstance(c,Dog) //Trueisinstance(b,Husky) //Falsedir()
获得一个对象的所有属性和方法,返回的是一个包含的字符串list使用
getattr()
、setattr()
以及hasattr()
,我们可以直接操作一个对象的状态:(attribute 属性)1234567891011121314151617181920212223242526272829class MyObject(object):def __init__(self):self.x=9def power(self):return self.x*self.xobj=MyObject()'x') # 有属性'x'吗?hasattr(obj,Trueobj.x9'y') # 有属性'y'吗?hasattr(obj,False'y', 19) # 设置一个属性'y'setattr(obj,'y') # 有属性'y'吗?hasattr(obj,True'y') # 获取属性'y'getattr(obj,19# 获取属性'y'obj.y19'power') # 有属性'power'吗?hasattr(obj,True'power') # 获取属性'power'getattr(obj,<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>'power') # 获取属性'power'并赋值到变量fnfn = getattr(obj,# fn指向obj.powerfn<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>># 调用fn()与调用obj.power()是一样的fn()81
实例的属性和类属性
我们经常给实例绑定属性,如果是类本身绑定属性,直接在class中定义类属性,其所有实例可访问,
使用__slots__
python是动态语言,我们很容易给class及其实例加上功能,用slots限制实例的属性:
|
|
__slots__
仅对当前类的实例有效,对其子类的实例无效,但如果在子类中定义了__slots__
,该子类的实例允许定义的属性就是两者之和。
定制类
__xxx__
的变量/函数是有特殊用途的。上面讲了__slots__
__str__
和__repr__
: 是用于打印显示更友好的信息print
,
|
|
但是在交互模式/命令行下,程序员输入After('Bob')
仍然会显示<__main__.After object at xxxxxxxxx>
而__repr__
就是面向程序员的,和__str__
同用法,或者直接在后面加上__repr__=__str__
__iter__
:用于类想的for in迭代
|
|
__getitem__
但iter吧就只能这么迭代算出结果,并不是保留了这些结果的list,你要Fib()[5]
是搞不成的,用__getitem__
方法就可以
__getattr__
调用了不存在的属性时会调用这个方法,所以他吗有什么用???哦,动态属性可以搞
__call__
调用实例本身,可以用callable()
函数判断对象是否是可调用对象(返回True or False)
使用@property
可以把一个方法变成属性调用。解决什么问题?:给实例直接绑定属性赋参数就没办法检查,但如果把检查参数的代写到一个专门set参数值的函数里又比较麻烦。
|
|
使用枚举类Enum
类似月份这种枚举常量,python提供了Enum
这个class,对于每一个常量引用一个实例
|
|
使用元类
用
type()
动态创建class对象123456789101112def fn(self,name='world'): #定义要使用的函数print('Hello,%s.'%name)Hello=type('Hello',(object,),dict(hello=fn)) #创建Hello类#type的三个参数:class名称/父类集合tuple(这里只有一个父类 tuple的单元素写法)/将已创建的函数与class的方法绑定h=Hello()h.hello()print(type(h))print(type(Hello))//Hello,world.<class '__main__.Hello'><class 'type'>metaclass
元类类的类??
多重继承
按照分类设计不同的父类,子类可以同时继承多个父类
IO编程
文件操作
读:打开文件 open(参数1,参数2)
参数1是打开文件的全名,参数2是打开方式。(文件存在则打开,不存在抛出IOError
|
|
写入文件write()
writelines()
针对列表,接受字符串列表参数并写入, 不会自动写入换行
文件遍历:模版如下
|
|
例子:拷贝文件
|
|
多文件读写 :例子:将两个文件合并
|
|
文件循环:
|
|
StringIO:在内存中读取str
os
模块操作文件
|
|
序列化
变量 从内存中变成可存储的过程 pickling 反序列化unpickling
|
|
使用dump()
方法的话这样写序列化对象后直接写入 file-like Object:
|
|
序列化为JSON
json嘛,js里面的标准对象类型,{} dict []list
|
|
|
|
进程和线程
多任务-进程Process 任务的多子任务-线程
?我不太明白在讲什么?系统调用 进程任务