目录
一、程序书写tips
多条语句可以放在一行,中间用分号“;”隔开
单行注释用"#"
多行注释用 '''或者""",,,,,但是前后要匹配
py的多行字符串可以用一边三个单引号(双引号)来标识
多行字符串可以通过三个连续的单引号(”’)或是双引号(“””)来进行标示,,,,也即和注释混用
py的单双引号作用相同,可以相互替换,但不能单引号与双引号配对
如果想在字符串里有单双引号,就要活用py的单双引号变换,双里可以括单,单里可以括双
转义字符是反斜杠"\",如果不想让反斜杠发生转义,可以在字符串前面添 加一个 r,表示原始字符串,,,r"asbh\nda"
Python语句中一般以新行(换行)作为语句的结束符
可以使用斜杠( \)将一行的语句分为多行显示
py的赋值操作可以用多个值赋多个变量,用逗号隔开就行了,会按照顺序进行赋值
py和java支持的都是unicode编码,对汉字和字母无差别对待
if __name__=='__main__':
pass //只有当该文件是操作系统入口文件时,__name__=='__main__'才为真
...
代码块是通过缩进来指示的
缩进表示一个代码块的开始,逆缩进则表示一个代码块的结束
声明以冒号 : 字符结束,并且开启一个缩进级别
二、multi-sources处理
py中的库其实就是Java中的包的意思,一个库就是一个目录(即文件夹),在目录下可以存放很多sources,且提倡一个源文件只写一个类,且类名和文件名保持一致,,当然一个文件可以写多个类,文件名和类名也没有必然关系
所以工程建好后就可以import不同的目录了,也可以使用圆点运算符import不同目录下的具体的类 库.类 即可
与Java不同,,Java是import到最终的类,,而py只能import包,最多定位到源文件上,但是不可能定位到源文件里的类或函数.
py一般采用这种 import 包 as 变量 => 对象=变量.源文件.类或函数(参数表)
python的import也要以工程目录为根目录,用点运算符向下拓展,与Java一样
python判断包(module)的方法是根据__init__.py文件判断的
以下为建立路径所使用的几个特殊符号,及其所代表的意义。
“./”:代表目前所在的目录。
“../”:代表上一层目录。
以”/”开头:代表根目录。
import库的写法
三、关键字
四、输入输出流
number = input("请输入一个数字:")-----------用于输入字符串并赋值
print输出默认换行
不想换行---print("lais",end=' ')
初始化变量时可以用0b表示输入的是二进制,,0o表示输入的是八进制,0x表示输入的是16进制
如果一个变量或表达式不进行赋值,则单独执行这一行会输出其值
print支持数值和字符串混合输出,只需要用逗号隔开
print的格式化输出:
print("%m.nf"%<数据>)
• %c 格式化字符及其ASCII码
• %s 格式化字符串
• %d 格式化整数
• %u 格式化无符号整型
• %o 格式化无符号八进制数
• %x 格式化无符号十六进制数
• %X 格式化无符号十六进制数(大写)
%#x 表示在打印16进制的基础上前面显示0x,方便人类阅读(八进制也一样)
• %f 格式化浮点数字,可指定小数点后的精度
• %e 用科学计数法格式化浮点数
• %E 作用同%e,用科学计数法格式化浮点数
• %g %f 和%e 的简写
• %G %f 和%E 的简写
• m.n m 是显示的最小总宽度(如果指定的话,缺省表示不指定),n 是小数点后的位数(如果指定 的话) (不够默认右 对齐, 左补空格)
• -用做左对齐
• + 在正数前面显示加号 +
• '%%'输出一个单一的'%
字符串对象有一个format()方法(方法前面要有原点运算符,而函数却不需要)可以指定在print()中输出的顺序
“:”指定了字符串输出的样式,控制样式的命令放在“:”的右侧, “:”的左侧则是替代的具体数据。
“今年,我的平均分为{:.2f}!”.format(96.3213)
右对齐与左对齐
format()方法的具体用法可以采用联机帮助
五、数据类型
(1)简单数据类型
int float double complex bool
py在定义变量时不能声明类型,否则报错,py的数据会自动选择类型
type()显示数据类型
bool()返回任意实例的真或假
py支持中文标识符,且英文和中文都是占一个unicode单位
想要表示复数,用a+bj或complex(a,b)来表示,其中a,b默认是浮点型的
py支持大数运算,int型是没有长度限制的
布尔类型, bool 值: True and False
不同数据类型的运算会自动转换成更宽的数据类型
py的标识符可以是汉语
(2)复合数据类型
len()函数返回一个序列的长度
py的复合数据类型元素以逗号做分隔,不像matlab中的空格
py的复合数据类型的索引和切片形式都是
<变量名>[<索引>] //注意是中括号
(1)列表(list)
python 中使用最频繁的数据类型 列表是写在方括号 [ ] 之间
列表中元素的类型可以不相同,它支持数字,字符串甚至可以包含列表 (所谓嵌套)
可以通过索引(下标)来访问列表元素 单个列表元素访问的语法格式为:列表名[下标]
下标从0开始,-1表示最后一个元素
列表截取(切片)的语法格式为:列表名[头下标:尾下标:步长],,,,步长可缺省,,结果不包含尾下标对应的元素
可以采用负数切片
(2)元组(tuple)
与列表类似,不同之处在于元组的元素不能修改
元组写在小括号 ( ) 里,元素之间用逗号隔开
元组中元素的类型可以不相同,和列表类似,也支持嵌套
元组的元素访问和截取方式和列表相同,通过下标来操作
元组一但定义好不能修改,是只读的
(3)集合(set)
是一个无序、且不含重复元素的序列
可以使用大括号 { } 创建
set() 函数可以把其他复合数据类型转换成集合
集合之间可以进行 交(&)并(|)差(-)补(^) 运算
其中补运算的含义是不同时在两个集合中存在,运算符是异或符号^
(4)字典 (dict)
字典用"{ }"标识,
它是一个无序的键(key) : 值(value)对集合
字典当中的元素是通过键来存取的
在同一个字典中,键(key)是唯一的,,且只能通过key来索引字典
(5)字符串
使用 + 进行字符串链接
"+"也可以合并所有复合数据类型
使用*进行字符串的复制,如下
"we"*3相当于"wewewe"
(3,4,)*2相当于(3,4,3,4) //第二个逗号可要可不要
不仅仅是字符串类型支持这种,其实所有的复合数据类型都是支持的
整型不能和字符串相加,与Java不同
字符串的format()方法可用于print()输出
复合数据类型的find()和index()方法返回所查找元素的索引,若查找不到返回-1
字符串的replace(m,n)方法,,用n来替换m,m和n可以不等长
Python中字符和字符串没有本质的区别
(3)数据类型转换
数据类型的转换,只需要将数据类型作为函数名即可使用 这些函数返回一个新的对象,表示转换的值,如: int(), float(), 和 str() 等
复杂数据类型之间也可以这样相互转换
另外字符串转换成对应的ASCII码值,需要调用以下函数
eval()的功能是“将任意仅含数字的字符串转化为有效的数字(根据情况可能是int型或float型)"
str()的功能与上述恰好相反,将纯数字转换为纯数字字符串
六、运算符
运算符优先级
运算符 | 描述 |
---|---|
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* / % // | 乘,除,取模和取整除 |
+ - | 加法减法 |
>> << | 右移,左移运算符 |
& | 位 'AND' |
^ | | 位运算符 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not and or | 逻辑运算符 |
py的整数除法是向负无穷取整数值的,求余也要根据求模来计算
!=和<>都表示不相等
py的与或非直接用英文表示:and or not
逻辑“与” :如果 x 为 False,x and y 返回 x,否则它返回 y 的计算值。
逻辑“或” :如果 x 是非 0,它返回 x 的值,否则它返回 y 的 计算值。
以上说明逻辑运算不具备交换律
逻辑运算中,False的值就是0
逻辑运算中,True的值就是1
逻辑运算中,非0的值只是视作True,但并不等于True。只有 1 等于 True
注意java的true和flase是小写的,且不能单纯的把flase看成0----,即0==false为假,,1==true为假
py没有m++和++m这样的自加自减
a,b=divmod(m,n) #a是m//n,,,,,b是m%n
abs()取绝对值,,也可以用于复数求模长
整数、浮点数和复数类型---------0是“假”,所有非0的数值都是“真”
字符串类型--------空串("")是“假”,所有非空串都是“真”
所有序列类型(包括字符串)-------空序列是“假”,所有非空的序列都是“真”
空值None表示“无意义”或“不知道”,也是“假”
七、控制流
(1)while循环
while 条件表达式:
语句块
(2)for循环
for 循环变量 in 序列:
语句块
range(m,n)表示从m开始到n(不包括n)结束的一个列表
下图的本质还是属于for循环(功能是把两列表元素两两进行算数运算,返回一个新的列表)
下图是列表的查找功能(m>x>n表示x位于m和n之间):
(3)循环控制符
break跳出当前层循环
continue 语句用来跳过当前循环的剩余语句,然后继续进行下一轮循环
pass 语句是空语句,是为了保持程序结构的完整性,一般用做占位语句
八、函数
return [表达式] 结束函数,选择性地返回一个值给调用方。
如果缺省return,则自动返回一个None,,,
如果只写个return,,也默认返回None--------(True,False,None都是大写首字母(关键字))
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明
调用函数的时候可以不按照顺序给形参传值,,在实参表里面只需要指定形参表变量就可以了,如下
def Sum(a,b,c): //定义函数
pass
temp = Sum(a=1, c=3, b=2) //采用指定形参的方式调用函数
函数可以返回一个元组(使用元组拆包可以有效返回多个值)
所谓元组拆包就是说以这种形式调用函数-----v1,v2,v3=fun(实参)
#################可选形参必须在必选形参的后面##############
• 全局变量在函数之外声明(全局可访问,包括函数内部)
• 局部变量在函数内容声明 (作用域和生存期在其函数内部)
由于函数内部创 建的变量只能在函数内部使用和访问,因此被称为局部变量(local variable),或者局部作用域。与之对应
如果一个变量在函数之外定义, 可以被程序的任何部分(例如其它函数)访问和使用,这样的变量称为全 局变量(global variable)
• 函数形参也是局部变量,不需要在函数内部重复定义!(作用域也在函数内部)(形参值的改变不影响实参,原始数据不受影响)
• 但如果想要修改全局变量的值,就必须在函数里面用global关键字进行声明这个全局变量,
否则Python会将此变量按照新的局部变量处理,且不影响原全局变量(请注意,这点很容易被坑)
可变参数的函数定义方式
def fun(*a): //定义了一个元组形参表的函数
pass
temp=fun(1,2,"yan") //为元组形参传递参数
temp=fun() //如果实参表为空,则形参元组是一个空元组
temp = fun(*b) //b是另外一个元组
可变参数的函数定义方式
def fun(**a): //定义了一个字典形参表的函数
pass
temp=fun(x=1,y=3,z="yan") //为字典传参
temp=fun(**b) //b是另外一个字典
匿名函数(lambda函数)
python中一些通用函数和方法:
排序:
列表对象的排序方法sort(),会对原列表进行排序
函数sorted()会对输进来的列表排序,并返回结果,,不改变原列表顺序
九、面向对象基础
python面向对象的深度理解请移步这里
python多继承和super()函数详解请移步这里
将数据和操作两者结合在一起,抽象出的一种实体,就是对象,一个对象也相当于是一种封装
对象又称作类的一个实例(Instance),类是相似对象所抽象出来的模板
面向对象语言强调以对象为中心,通过对象与对象之间的信息交互来实现我们需要的功能
py中一切都是对象,大到类,小到一个数字都是一个独立的对象
类的定义:
class <类名>(object):
<类属性> //类属性属于类,不属于任何对象
def __init__(self, <参数表>): //构造函数
pass
def <方法名>(self, <参数表>): //self必带且放第一个位置上,其他参数可选
pass
<与class类同级的函数或变量>
对于py来说,属性指构造函数中的属性(即实例属性),而不是类属性
实例属性于每个实例各自拥有,互相独立,而类属性有且只有一份。因为类属性是直接绑定在类上的,所以,访
问类属性可以直接用类名访问,也可以使用实例名访问因为类属性只有一份,所以,当类属性改变时,所有实例访问到的类属性都改变了(经过类名修改类属性).
注意:如果是通过实例名修改类属性,则实际上是给实例绑定了一个与类属性同名的实例属性,而访问时会优先访问实例属性
如果属性名或方法名以双下划线开头且不以双下划线结束,则该属性或方法是一个类内部的私有属性或方法,无法通过该类创建的任何对象访问(可以通过该类中的方法访问)(这是一种数据隐藏的做法,提倡使用)
py是一个动态语言,任何时候都可以自由的为实例添加任何属性,而不限制于构造函数的参数表(破坏性非常大)
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象,因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType(function,instance) 把一个函数变为一个方法,再赋值给instance的方法
和属性类似,方法也分实例方法和类方法。
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。
要在class中定义类方法,我们通过标记一个 @classmethod,该方法将绑定到类上,而非
实例上。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,下面例子中
的 cls.count 实际上相当于 Person.count。
class Person(object):
count = 0 //类属性
@classmethod /* 类方法
def how_many(cls):
return cls.count */
def __init__(self, name):
self.name = name //实例属性
Person.count = Person.count + 1 //实例方法
print (Person.how_many())
p1 = Person('Bob')
print (Person.how_many())
******************************
输出:
0
1
创建对象:
obj = <类名>(<参数表>) //注意小括号,,参数不会赋给self所以千万不要写上赋给self的实参
总而言之,形参一定要带上self,实参一定不能带self对应的参数
self指对象本身
类的三个特性:
①封装性:封装有两个含义。第一个含义是,把对象的全部属性和全部行为结合在 一起,形成一个不可分割的独立单位(即对象);第二个含义也称作“信息隐蔽”, 即尽可能隐蔽对象的内部细节,对外形成一个边界(或者说形成一道屏障),只保留 有限的对外接口使之与外部发生联系。
②继承性:可以从现有的类出发,定义新类,新定义的类为子类。子类继承父类的变 量和方法,并且另有自己的变量和方法。继承的好处是代码重用。
③多态性:父类中定义的属性或行为被子类继承之后,可以具有不同的数据类型或 表现不同的行为。这使得同一个属性或行为在父类及其各个子类中可以具有不同的语 义。
其实一个个对象也是一个复合数据类型,把他当作普通的数据类型去使用就可以了
在py中,同一个类的不同对象在内存中标记为不同的id,即不同的对象位于不同的地址
py中的变量引用(即赋值操作),是使得不同的变量指向了同一个地址,即使用了同一个id,,,
函数传参一般情况下不是变量引用,而是变量的值的简单复制
Python中约定,类名用大写字母开头,函数 用小写字母开头,以便区分(和Java的命名方式接近)
对象构造器 __init__(self,[…) //对象的构造器,实例化对象时调用
析构器 __del__(self,[…) //销毁对象时调用
构造函数式 __init__(),也就是当该类被实例化的时候就会执行该函数,__init__()方法是可选的,如果不提供,Python 会给出默认的__init__方法。
“__del__()"就是一个析构函数了,当使用del 删除对象时,会调用他本身的析构函数(如果函数有具体功能,还会执行这个功能),另外当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次(如果你没有缺省掉析构函数,也会执行函数里的功能),这样可以用来释放内存空间。_del__()也是可选的,如果缺省,则Python 会在后台提供默认析构函数
py的垃圾回收机制
1>Python 采用‘引用计数’ 的算法方式来处理回收,即:引用该类的对象为0时,程序就会自动执行析构函数
2>当一个类有多个对象时,可以使用del关键字删除某个对象 del obj1号 obj1号被删除后在内存中就不存在了,每del一个对象,析构函数就执行一次(且每次self都是指被del的那个对象)
3>除非你把所有对象删完,析构函数才会执行
4>析构函数是可以缺省的,系统会自动隐式调用析构函数,,如果想在析构函数中实现一些具体的功能,用户可以把它写出来,添加函数功能,这样析构函数被执行时,会执行这些具体功能
5>在创建对象时,构造函数会执行一次,在所有对象都消亡时,析构函数会执行一次,
由于构造函数和析构函数是对外可访问的,所以在任何时候用户都可以调用该俩方法,但是仅仅只是执行了函数而已,
py的垃圾回收机制是其自己管理的,用户几乎无法控制
class test(object):
def __init__(self,a):
self.name=a
print(self.name)
def __del__(self):
print("已析构",self.name)
def show(self):
print("已执行show")
t1=test("t1")
print("*****")
t1.__init__("newt1")
print("*****")
print(t1.name)
print("*****")
t1.__del__()
print(t1.name)
print("*****")
t1.__init__("newnewt1")
print(t1.name)
t3=test("t3")
# del t1
t1=test("t4")
print(t1.name)
*********输出*********
t1 //创建对象时,自动执行构造函数
*****
newt1 //用户调用__init__方法
*****
newt1 //查看属性是否改变,发现改变了
*****
已析构 newt1 //用户调用析构函数
newt1 //查看用户调用的析构函数是否删除了对象,发现没有
*****
newnewt1
newnewt1
t3 //创建新对象
t4 //创建第三个新对象并覆盖第一个对象
已析构 newnewt1 //发现在调用了构造函数后,自动析构了第一个对象
t4 //用print查看属性
已析构 t3 //程序执行结束,析构t3对象
已析构 t4 //程序执行结束,析构t1对象
****************************************
此例说明:
(1)用户自己调用的析构函数不会删除对象,但可执行函数里的语句
(2)用户可以随时重新初始化已有的对象
(3)每del一个对象,以该对象为self的析构函数就会执行一次
(4)在程序执行完毕时,对存在的对象,每个都会执行一下析构函数
类的单继承(S-inheritance)
class <子类名>(<父类名>):
<子类的全局变量>
<子类的构造函数> /*如果子类不写构造函数,则自动调用父类构造函数.如果子类写构造函数(注意子
类构造函数参数表必须包含父类构造函数参数表),则不会自动调用父类构造函
数,可以自己加上去,见下!*/
<子类新的方法或改写父类方法> //所谓重构是改写父类方法,所谓派生是添加新的方法
...
子类构造函数引用父类构造函数有两种方式: /*子类的构造函数参数表需要包含父类的
构造函数参数表,否则没法传参*/
1.经典类的写法: 父类名称.__init__(self,参数1,参数2,...)
2.新式类的写法:super(子类,self).__init__(参数1,参数2,....) /*父类也称基类或超类,所有
有了super()函数*/
// py3中可以写成super().__init__(参数1,2,3)
类的多继承(M-inheritance)
没有内容
一些接口问题
单下划线开头:
单下划线开头的命名方式被常用于限定访问范围位于当前模块中。在另一个模块使用 from my_module import * 导入本模块时,单下划线开头的变量和方法是不会被导入的。但使用 import my_module 导入的话,仍然可以用 my_module._var 这样的形式访问属性或方法。
双下划线开头:
的命名方式有实际的作用,采用这种命名的变量或方法无法直接通过 “对象名.变量名(方法名)” 这样的方式访问。
双下划线开头和结尾:
是一些 python 的“魔术”对象,如类成员的 __init__、__del__、__add__、__getitem__ 等,以及全局的__file__、__name__ 等。 python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数.
__all__=[]的问题
Python 可以在模块级别暴露接口:(只是针对import *,,)
__all__ = ["foo", "bar"]
__all__
是对于模块间公开接口的一种约定,比起下划线,__all__
提供了暴露接口用的”白名单“。一些以下划线开头的变量,,也可以通过放在方括号中,被模块外的程序import *导入,,相反,未在列表中的任何变量,也将无法被import *导入
如果显式声明了 __all__=[]
,import *
就只会导入 __all__
列出的成员。如果 __all__
定义有误,列出的成员不存在,还会明确地抛出异常,而不是默默忽略。
__all__ = [
"foo", //可以是类,方法,变量,函数名
"bar",
"egg",
]
__init__.py的问题
如果你是使用python的相关IDE来进行开发,那么如果目录中存在该文件,该目录就会被识别为 module package 。
如果目录中包含了 __init__.py 时,当用 import 导入该目录时,会执行 __init__.py 里面的代码。
__init__.py里面一般写如下内容,也可以是空文件
__all__==[<"要列为对外模块白名单的源文件名">]
from <从根目录开始的完整路径>.--- import *
十、文件操作
文件类型:
文本文件: 只包含基本的文本字符,包括字母、数字、标点符号 和一些特殊字符如换行符,但不包含字体、大小和 颜色信息。
二进制文件:除此之外所有其它文件类型都称为二进制文件。
在Python中,二进制文件和文本文件的操作步骤是相同的(但是具体函数不同):
①打开文件,获得该文件的使用权
②对文件进行读写操作
③关闭文件,释放对文件的控制权
(1)文本文件
(1)文件的打开:
用open()函数打开文件,并赋值给文件对象
My_file=open(‘C:\\Python32-36\\my_file.txt’,‘r’)
(2)文件的操作:
Python读取文件有3种方法:
− read()方法: 读取整个文件的内容返回为字符串
− readline()方法: 只读取一行(可以通过循环遍历)
− readlines()方法:读取整个文件的内容返回为字符串列表类型
Python的文件写操作与上述类似
文件指针
seek(offset,[whence])方法将文件指针从参数whence移动到参数offset指定的位置:
− offset=0,移动到文件起始位置
− offset=1,代表指针当前所在位置
− offset=2,移动到文件结尾
可选参数whence表示从哪个位置开始移动文件指针:
− whence=0,表示从文件起始位置移动
− whence=1,表示从当前位置移动
− whence=2,表示从文件结尾处移动
通常把指针移动到希望的位置进行读写
也可使用下图方式:
序号6的一般形态是 'w+' 则表示在w功能的基础上增加读写功能,'r+' 'a+'也一样
(3)文件的关闭:
用 文件对象.close() 关闭
(2)二进制文件
文件的打开
需要向import PIL 的库,该库中有21个类,我们使用Image这个类(注意大小写)
pip install pillow //不要使用conda安装,conda安装的包都很老
from PIL import Image
文件对象=Image.open("文件目录") //该类提供了很多属性和方法,可以联机帮助查找
待定...
(3)网络爬虫
在Python中,抓取网页并从中获取数据需要两个步骤:
①通过网络链接下载网页,使用requests库
②解析网页格式,获取其中的数据,使用beautifulsoup4库
十一、异常处理
十二、图形界面与可视化
没有内容
十三、多线程机制
没有内容
十四、数据库编程
没有内容
十五、获取帮助
使用help(对象名)可以获取该对象的内部情况,包括属性和方法
也可以使用dir(对象名),,仅仅只获取该对象的所有方法