1.python的特点
与其他机器语言的不同就在于python支持交互式编程,在原生平台可以随时查看结果。与编译型语言不同,python在运行时才将内容解释为机器语言,而C/C++在进行编译后,以后运行时就不需要再进行编译,所以执行效率会高很多,但python拥有强大的库,拓展性极强,优势也很明显,可以满足很多场景的使用,相对于底层的语言,封装了很多方法,使用起来更为方便,学习起来因为很多时候可以不管实现的原理,所以相对更为容易,但是掌握原理有利于掌握的更深,所以还是建议多去了解各种方法的实现原理。
开始学习一门机器语言时,程序莫过于学习背景特点,学习数据类型,学习数据的操作(包括运算符和常用的方法以及自定的方法),进入该门语言的核心部分(面向对象编程的三特征与实现,或者C的精华指针部分),总的层次相差不多,本文只回顾最基础的部分,高级语法oop编程和socket等另行记录
2.python的基本语法
谈到基本语法不提变量当然不行,与其他语言有所不同,python的语法中提倡变量名、函数名、模块名小写,而对类名才推荐大驼峰规则,即首字符大写,其次从意义上来说,也推荐变量名为名词,函数名为动词,而常量则大写,还有在python中boolean值为True与False要区分大小写,还有万年不变的要避开关键字,以免解释器解释的时候可能混淆。
除此之外,python还有个大特点就是代码块的层级是通过:与缩进合作完成的,所以在使用时,一定要注意这两部分,少了:或者缩进不对都是有问题的。
在注释方面,单行为#开始,多行使用三个单/双引号开始三个单/双引号结束。
简单的输入输出:input("提示信息"),要注意得到的是字符串,操作时可能需要进行类型转换
print(val1,val2,sep='',end=''),默认sep与end为空格与换行,可自己指定,sep为val1与val2中间间隔的 的内容,end为print执行完成后的操作,在输出时,还可以通过'''来原样输出(保留所用空格回车)
3.python中的数据类型
总的来说,python中的数据类型分为数字,字符串,列表,元祖,集合,字典,考虑到抽象类型还有类,对象等,而每一种数据类型在实际使用时也有各种特点,互相之间也有嵌套的可能。以下谈一些对各种数据类型的理解:
'''
I.数字类型:
数字类型总的来讲包括了:
1.整形int 2.浮点型float 3.复数(通过方法实现complex(实部,虚部)) 4.分数(需要导入包中类)
补充:在使用pymysql处理数据库时,会发现数据库中很多数据时decimal(m,n)的类型
处理方式:import decimal
然后将float类型的数字强转类型为decimal:decimal.Decimal.from_float(浮点数)
这样就可以完成计算后给数据库中对应值进行更新
数字类型并无大坑,所以不多做解释,要注意的就是类型而已
'''
'''
II.字符串类型
字符串类型主要的操作包括索引和切片,除此之外还有很多类方法可以使用。常用的如下:
'''
string = 'hello,world!'
#索引:
string[index]
#需要注意的就是索引范围,python自动处理了下标负数的情况,就是从倒数第index位,因此index的范围为-length<= index <length,即[-length,length)
#切片:
string[起始位置:结束位置(不包含此下标):步长]
#索引时需要注意起始应当在结束之前,步长为负时是从尾部向前切片,如果给出的结束位置大于字符串长度,则默认到字符串结束就问完成,第二个参数的结束位置是开区间,不包含在最终结果中
#常用类方法:
len(string) #求字符串长度,库方法,还可求列表等的长度
del string #删除字符串。库方法,变量名会自此失效,类似于C里的free,是直接释放了数据,终止了引用
max(string)/min(string) #求字符串的中ASCII码最大或最小的字符
string.count("",begin,end) #指定范围查找指定字符的个数
string.title() #每个单词首字母大写
string.capitalize() #仅第一个单词首字母大写
string.find("",begin,end) #查找第一个该字符的下标,如果找不到则返回-1
string.index("",begin,end) #与find区分开,如果没有找到则会抛出异常终止运行,可以理解为find是试着去找,而index应当在知道字符串中包含该字符的情况的想得到该字符下标时使用的方法
string.isalpha() #是否都是字母
string.isdigit() #是否都是数字且至少有一个数字
string.isdecimal() #是否是十进制数(如果拿来判断二进制数则会返回FALSE)
string.isalnum() #是否只包含数字或字母
string.upper()/lower() #将字符串中的所有字母大写或小写
string.swapcase() #字符串中所有字母大小写转换
string.strip('')/lstrip('')/rstrip('') #将前后/头部/尾部指定字符删掉(不会处理中间的内容,常用来删除前后的空格)
str2.join(str1) #将str2作为填充物填充到str1中各字符之间
string.remove(old,new,max) #替换字符串中的old为new,最多替换max次
string.split("",num) #以""分割字符串,num指定切割次数,最终分割为num+1个字符串放在列表中
#III.列表(类似数组)
# 定义:(命名常为复数,必须存放student名称的列表可以叫students或者names)
my_list = []
my_list = [i for i in range(50)] 列表解析式创建
# 索引与切片与字符串类似,不做过多解释
# 常用类方法:
my_list[index] = value #更改指定下标的值
my_list.append(内容) #在尾部添加指定元素
my_list.insert(index,内容) #在指定下标位置插入新元素,原来该位置起的元素都在以此向后移动
del my_list[index] #删除指定下标的元素
my_list.pop(index) #删除指定下标的元素,并将其值返回
my_list.remove("") #根据值删除内容,如果有多个符合的则删除第一个符合的
my_list.sort() #对内容进行排序,排序完成列表自身会改变
sorted(my_list) #调用库方法,该方法返回一个排序后的备份,不会改变原来的列表顺序
#IV.元祖(形式上类似于特殊列表,常用来存储在程序运行中不会变化的值)
# 定义:
my_tuple = () #元祖不支持解析创建
# 同样可索引切片,方法也相同
# 元祖变量突出一个数据不可改,至少不可原址修改,想要修改元祖中的内容(包括追加)最终得到新元祖都只是形式上增加或者改变,从地址来看已经是新的元祖了,如果要对内容进行修改,则必须重新定义去修改
#V.集合(此处集合与一般数学中的集合相同,当不在乎数据位置,只在乎其中有何物时可用集合)
# 定义:(定义集合时,在进行初始化时各元素的顺序是不确定的,但是一旦初始化结束,视觉上顺序是定了,但是仍不可索引)
my_set = {1,2,3,4,5}
my_set = set({2,3,4,4})
# 其中,使用set进行初始化时,只要是可遍历的数据都可以,将每个遍历单位作为集合的元素,比如使用字符串时,最终集合内容就是字符串中每个字符
# 集合不可索引,出于其定义时的目的,本身也就不应该关注索引,不支持索引自然也与切片无缘
# 集合可进行的操作:
set1 & set2 #求交集
set1 | set2 #求并集
set1 - set2 #求差集
set1 ^ set2 #求交叉差集,互差然后并集
myset.add() #添加元素
myset.remove() #按值删除内容
#VI.字典(键值对的组合,索引时类似下标自定义的列表)
# 定义:
my_dict = {key:value,key:value,key:value}
# 字典的索引:my_dict[key] 通过键进行索引,字典不可索引,因为不是哈希结构
# 常用的使用:
my_dict[key] = value #修改值,如果key不存在则为添加元素
new_dict = my_dict #浅复制,并没有复制内容,只是增加一个引用,赋予new与my相同的地址指向
my_dict.copy() #深复制,即将内容复制一份,存放在别的地址
my_dict.fromkeys() #以序列seq中的元素(集合也可以作为该参数)做字典的键,val为字典所有键的初始值
my_dict.get(key,default=None) #按键查找,找不得则返回default指定的值
my_dict.keys()/values() #以列表形式返回一个字典的所有键/值
my_dict.setdefault(key,default=None) #如果键不在字典中,则自动添加(与直接使用索引的区别感觉不是很大,二者返回的ID都是相同的,都是同一个地址)
my_dict.update(update_dict) #对my_dict操作,共有的键则将其值更新为update_dict中的值,如果没有将其添加在my_dict中(类似于版本更新)
在了解上述数据类型的基础特性后,对比抽象下它们互相之间的特点与规律:
'''
1.可变数据类型(mutable)与不可变数据类型(immutable)
可变:list,set,dict 有公用的方法clear(),pop(),remove()[dict没有remove方法,只能使用pop与del]
不可变:number,string,tuple
1.集合中的元素不能为可变类型(比如列表,集合)但是可以是元祖(因为元祖不可变)
*使用set方法时,要注意括号内的第一层为传入的序列,实际在构造时是将序列内的元素进行逐一的操作,所以不能因为([])或者({})就认为set方法可以打破这个限制
2.字典中的key不能为可变数据(要进行索引自然不能有二义性)
字典中的key不能重复,类似于set={'a':1,'a':2}最终结果只有一个key为'a'且值为最后一个'a'对应的
3.求字典中值最大并将键也输出的方法之一:
max_result = max(zip(dict.values(),dict.keys()))
'''
4.python运算符
总的来说python的运算符分为算术运算符,比较运算符,逻辑运算符,成员运算符,赋值运算符,位运算符,具体的情况如下:
'''
1.算术运算符:
+,-,* ,% :基本的运算,加减乘和取余运算
/:python支持整整除得浮点,一个除号结果不会取证,由于数据都是二进制存储,在存和读的过程中小数可能会丢失精度
//:两个除号表示求整除,除完会取整
x**y:幂运算,x的y次方,还提供了方法完成,pow(x,y)与其等效
2.比较运算符 : ==, >=, <=, <, > !=
在处理特殊的数据类型时,比如布尔型和None时,要用到 is与is not
3.逻辑运算符:常用的为短路运算符,即第一句如果能判断出整个表达式的结果,则不会执行第二句 ,与java中的&&与||相同
and /or :可以使用短路运算符实现建议的条件分支效果:
if a>b :
print(a)
else:
print(b)
等价于:
a>b and print(a) or print(b)
4.成员运算符:in 唯一主要注意的就是在value in dict时,默认为检查key中有没有等于value的。支持除数字外的所有数据类型
5.赋值运算符: +=,-=,/=,//=,*=,**=
6.位运算符: &,|,^,~,<<,>>,按位与、或、异或、取反,左移右移
*需要注意的是计算机存储数据本质上都是以补码的形式在存在,所以位运算都是对存储在计算机中的补码进行位运算,然后运算完之后再将新补码转换为反码,然后转化为原码显示。
具体的规则:正数的反码与补码都是其自身;负数的反码为符号位不变其它位取反,负数的补码为其反码加1
'''
5.python控制结构
与其它语言没有本质区别,只是语法稍微不同,特殊的就while else结构,其余的大体也是顺序结构,分支结构(if,if...else...,if...elif...else...,while...else),循环结构(for,while),需要注意的如下:
#for 循环实例:
for i in range(0,3,1):
print(i)
# 从0-2,每隔1个数打印一次,range的前两个参数为范围,左闭右开,第三个参数为步长,默认为1,除了使用
range还可以使用,其他可遍历的数据类型,取决于成员运算符in的可用范围
#while 循环实例:
count = 3
while count > 0:
count -= 1
my_str = input('请输入选项:1.继续 2.退出')
if my_str == '1':
continue
elif my_str == '2':
break
else:
print("请输入正确的选项")
else:
print('三次机会用完')
'''
上述例子中展示了if分支和while循环以及while...else结构的类条件结构
有种说法是for循环常用于循环次数已知,while则用于未知,其实二者没有绝对界限,都可完成已知与未知
在上述代码中,给三次机会输入选项,如果输入1则继续,输入2则退出,如果是其他输入则提示重输,不论最终输
入为何都将消耗一次次数,如果输入已知不为2,则进行三次后while循环结束,此时else发挥作用提示三次机会
用完,如果是中途输入了2则while没有自然执行完,不会进入else的三次机会用完
while...else...中其实就是while如果是自然执行完则进入else,如果是使用break跳出,则不会进入else;使
用这种结构可以减少一层嵌套,让代码更加美观,也符合python所提倡的风格
'''
6.函数
使用函数的意义不再多说,直接谈python中函数定义的语法与特点:
#以一个实例函数为例:
def my_func(args1,args2,args3=default_value):
pass
#不定数量参数:
def my_func(*args):
pass
#在定义函数时,可以给部分参数设置默认值,当没有传入时,会使用默认的值,但是应当把有默认值的放在最
#后,如果参数的数量不确定时,可以使用*args作为参数,其本质就是一个元祖,在操作时也当元祖对待
#函数的调用:
#位置参数:
my_func(para1,para2)
#使用位置参数时,参数的顺序应与定义的相同
#关键字参数:
my_func(args2=para2,args1=para1)
#关键字参数可无视顺序,但关键字要正确
#默认值参数:
#定义时的特点,可以为某个参数设置默认值,但是其后不能再有位置参数
#不定长参数:
#即上述的*args
#形参与实参的区别:
#实参是在调用函数时传给函数入口的参数,而形参是其复制品,将其复制了一份交给函数操作,在函数调用结束时会自动释放
除了基本的定义与调用时的一些特性,还有LEGB原则:local,enclosing,global,built-in;其中enclosing为函数嵌套调用时的情况,global也需要慎用其相当于java中的static。
除此之外,在函数进行定义时,还可以加入文档字符串来描述函数的信息,在函数定义的冒号后紧接着第一行写使用'''来描述即可。此外还值得注意的有lambda表达式,它允许进行函数速写,使用一行完成一个基本的函数:
my_func = lambda x,y:x+y
#调用:
result = my_func(1,2)
7.pymysql连接数据库
本质上就是导入了pymsql模组,然后创建连接对象,再调用对象的属性与方法进行操作,常见用法如下:
import pymysql
# 自定数据库连接函数,返回一个连接对象,通过这种方式可以方便自己使用数据库,不用每次创建都手动输入参数名(这里有个坑是默认是3306端口,如果自己配置过mysql的端口,登录被拒绝的时候可以检查下端口)
def my_connect(host = 'localhost',user = 'root', password = '123456', dbname = 'woniuatm'):
db = pymysql.connect(host, user, password, dbname)
return db
# pymysql操作
# 自定增删改方法,传入sql语句,进行数据修改,此处不能忘记commit否则数据未提交
def database_mani(sql,dbn):
db = my_connect(dbname=dbn)
cur = db.cursor()
cur.execute(sql)
db.commit()
cur.close()
db.close()
# 自定查询方法
def database_query(sql,dbn):
db = my_connect(dbname=dbn)
cur = db.cursor()
cur.execute(sql)
result = cur.fetchone() #此处还有fetchall可用,区别在于fetchall为全部结果,fetchone为
cur.close() #一条一条输出,结果而言,fetchone是一个元祖,而fetchall是两个元祖的嵌套索引
db.close() #时要注意区别
return result
8.python如何使用文件作为I/O
# 过程其实很简单,就是单纯的调用库中的类与方法完成操作,以下只列出值得注意到地方:
# 打开/关闭文件:
file = open(path,mod="",encoding="")
file.close()
# 其中,mod是指打开的模式(限制了可进行的操作),encoding是字符集的选项,一般使用ASCII码的字符不会出现字符集的问题导致乱码
'''
这里边必须要注意的就是mod对应的几种选项(在第一次使用时会有几个小坑):
r:当不显式指定时,默认就是r,该模式下只能进行读取的操作
r+:可进行读写,这种模式下,指针会在文件内容的头部,如果进行写入操作,会依次进行覆盖,文件不存在时会报错
w:只写入,如果文件存在,则执行的是覆盖旧内容的写入,若不存在,则创建该文件。这种方式下使用readlines方法会有异常
w+:读写,如果存在则覆盖写入,如果不存在则创建改文件;readlines使用时不会报错,但是实际得到的结果为空,所谓的读写其实能实际操作的还是写入操作
w与w+有一个很强烈的特性:只要是使用这两种方式打开文件了,则会默认先将旧内容清除掉,也就是说就算不进行write,只要有open操作,哪怕是紧跟着就close,原内容也会丢失
a:追加写入,指针在文件内容尾部,如果文件存在则追加不存在则创建文件写入该内容
a+:读写追加,与w类的情况相同,实际上使用readlines得到的是空列表
常用:w主要用于修改中间元素,因为这种方式下最终返回的结果是一个元素为每行字符串的列表,要想对其中的某一部分进行修改只能修改该地方,然后将整体覆盖写入文件。这也是为什么使用文本文件存储数据效率不高的元素,因为没办法完成真正意义上的修改元素
a主要用于添加新元素时,相对于原来的有全新的数据时比较常用
方法:
file.readlines() 将文件内容全部读取,以行为单位存放在列表中
file.readline() 将一行内容读取,与游标类似,在取出一行后会改变地址指向下一个内容,所以如果先readlines,指针指向没内容的地方,再运行readline时结果自然是空
file.write() 对内容进行写入操作
'''