学习一门新的语言,应当抓住语言的共有特性,这样容易触类旁通,学习起来也十分的快捷愉悦
而语言的特性大约有以下元素
变量定义与类型
算术符号与逻辑符号
for 循环与 while 循环
数组,线性表等一些常用的数据结构
函数的定义与调用
递归
静态类型系统
类型的推导
lambda 函数
面向对象
垃圾回收
异常检测
如果你对一个语言以上的元素都有了大致了解(事实上其实并不需要花太多时间),那么你就可以愉快的开始使用啦~
1.变量的定义与类型
变量的定义
python里变量的定义十分简单 不需要像java里需要进行声明
例如 i = 0
变量的类型
Pyhton里的变量类型分为整数型(int) 浮点型(float) 字符型(str) 布尔值类型(bool)
其中bool类型的对错是首字母大写的True与False,非0的字符(包括int,float,str)如果转义会被转成True 而0则是False这点有点类似于Javascript
字符串的格式化
python中的字符串支持参数的方式 如"{a} love {b}".format(a="i", b="u") 结果为 i love u 可以看作是使用了变量进行了代替
同样可以使用数字位置的参数进行替换如'{0} love {1}.format('i', 'u')' 结果为 i love u
如果限制格式那么使用 : 例如 '{0:.2f}'.format(45.5688) 结果为 45.57
要进行格式化操作的话 这样使用 '%c' % 97 结果为a ,因为%c 是进行ASCII码的转化 ,多个参数使用元组或者字典 '%d + %d = %d' % (4,5,9.1) 结果为 4 + 5 = 9 , 这里用一个列表介绍各种格式符号的意思
符号
含义
%c
格式化ASCII码
%d
格式化整数
当然还有一些是用来辅助操作的
符号
说明
m.n
m是显式的最小总宽度,n是小数点后的位数
-
用于左对齐
+
在正数前面显式加号
#
在8进制前面显示0,在16进制数前面显式0x或者0X
0
显式的数字前面填充0取代空格
2.逻辑符号与运算符符号
逻辑符号
and or not 对应java的 && || !
运算符
基本运算符包括 + - * / ** //
** 的意思是阶乘 例如 3 ** 2 = \(3^2\) = 9
python里/ 除号默认是float,若要变成类似java的两个取整的,就使用//符号 例如 3/2=1.5, 3//2=1
3.For循环与While循环
for循环
for i in range(0,10):
print (i, end='')
输出结果0 1 2 3 4 5 6 7 8 9
pyhton里的for循环类似于java5中的foreach循环,对循环体里的每个对象进行操作
while循环
i = 0
while i < 10:
print(i, end=' ')
i += 1
输出结果0 1 2 3 4 5 6 7 8 9
需要注意的是python里的循环体语法后面要加上一个冒号哦 :)
4.数组,元组与线性表
数组中常用的api
可以通过dir(list)来查看相关api
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
构建一个数组 array = [1,2,3,'hello']
要添加元素使用append,array.append(x)
extend类似于java里的addAllarray.extend(list2())
removearray.remove('hello')
按照下标删除数组里的东西 del array[1] ,如果是del array,那会直接把这个那个数组删除掉
也可以使用pop()函数array.pop(),不写参数时是默认删除最后一个元素,可以通过填写下标来删除指定的元素
数组的分片array[a:b],a代表可以的索引值,b代表结束的索引值(但是不包括这个元素),例如array[0:2]就等于
[1,2],也可以不指定a或者b,这样是默认从头开始,一直到结尾,例如array[:] 获得了原数组的拷贝[1,2,3,'hello']
reverse,array.reverse()数组列表反转
count,array.count(1),统计数组里1出现的次数
index,array.index(1)返回指定元素的下标
其他方法自己看api啦
数组中的操作符
使用操作符 + 对数组进行拼接,例如list1 = [1, 2] list2 = [3, 4] list3 = list1 + list2,那么list3里面内容就是[1,2,3,4] 但是需要注意的是 + 操作符两边的对象类型要保持一致 list3 = list1 + 3显然就是错误的
使用操作符 * 可以达到数组的拷贝与拼接例如进行array *= 2的操作过后array =[1,2,3,'hello',1,2,3,'hello']
使用操作符 = 可以达到数组地址的引用
in与not in 返回一个bool类型的结果,例如 'hello' in array 返回True 'hello' not in array 返回False
元组(tuple)
元组的操作和数组十分类似,不同的是元组是不可变的,可以理解为java里的final类型的数组
元组的构建的核心是 , 逗号tuple01 = (1),这样的构建方式type(tuple01)的结果就是int, 正确的构建方式是类似于这种tuple01 = (1,) tuple01 = (1, 2, ) ,如果要构建一个空的元祖使用 tuple01 = ()
如果要对元组进行更新,删除,添加等改变状态的操作,一般是使用: 重新构建出一个新的元组,例子如下
tuple01 = (1, 2, 3)
#下面我想要在该元组后面加入一个新的元素
tuple02 = tuple01[:] + (4,)
print (tuple02)
#那么tuple02 = [1,2,3,4] , 那么更新与删除的操作与上面就同样类似了
线性表
集合的本质是由数组构成的有序线性表,因此大部分语法与数组相同
集合的构建 list()空列表 list(iterable) 参数为可迭代的对象 >>> b= 'I LOVE YOU'
>>> b = list(b)
>>> b
['I', ' ', 'L', 'O', 'V', 'E', ' ', 'Y', 'O', 'U']
集合的正常操作api与数组和元组十分类似,可以使用help(list)进行查看
一些集合中常用的辅助函数 假设有这么一个集合 list1 = list([1,2])
sum()求和 sum(list) 结果为3
max(),min()最大值与最小值
enumerate() 将索引与值拼接成一个元组返回 list(enumerate(list1)) 结果为[(0, 1), (1, 2)]
zip 打包 list2 = list([3,4,5]) 根据索引值将2个集合的数据拼成一个元组返回 例list(zip(list1,list2))
结果为[(1, 3), (2, 4)],对应不上的就舍去了,所以5没有在结果中
5.函数的定义与调用
函数的定义
def helloWorld():
print ('i love programe!')
python中的函数参数形式
指定参数传递 def say(name, word):
print (name, 'say', word)
say(word = 'hello!', name = 'I') 输出结果为I say hello!
默认参数
def say(name = 'i' , word = 'helloWorld!'):
print(name + '\rsay\r' + word
say()
say('you','good')
输出结果为 >>> say()
i say helloWorld!
>>> say('you', 'good')
you say good
参数列表
def say(*name):
for x in name
print (x)
say(1,2,3)
输出结果为1,2,3
一般使用参数列表建议后面的参数使用默认参数例如
def say(*name, word='say hello!'):
for x in name:
print (x, word)
函数(function )与过程(produce )
在python里没有过程,只有函数,即使是没有return的函数依旧有一个返回值,这点与java不同
测试
def voidType():
print ("Hello World!")
#打印出该函数的返回值
print (voidType())
#使用type函数来获得该函数的返回值
type(voidType())
结果如下
>>> print (voidType())
HelloWorld!
None
>>> type(voidType())
HelloWorld!
可以看到打印的是None,而使用type函数得到的结果是NoneType,说明了在python中没有produce只有function
函数关键字global
在python中的函数不能对外部变量进行修改,可以访问,这点与java8的函数类似,也保持了函数无状态的性质。
关键字global的使用,看下面这个例子
count = 5;
def myFun():
count = 10
print(count)
myFun()
print(count)
运行结果是 10
5
在python里如果在函数里定义了局部变量,变量名与全局变量相同(在上面的例子是count变量分别在外部和函数里被定义了一次),那么函数体内使用的就是局部变量(采取了就近原则)
如果要定义全局变量,使用global关键字
count = 5;
def myFun():
global count #这里的定义是不能直接赋值的,比如global count = 10 这种写法
count = 10
print(count)
myFun()
print(count)
运行结果是 10
10
注意,这里看起来是对全局变量进行了修改,但我的理解是这里并不是进行修改,是内部重新定义了一个全局变量count,然后进行了赋值,自然就覆盖掉了全局的变量,依旧没有打破无状态的原则。
与其他语言的对比
与java的对比
访问与修改
在java中,在方法中可以访问和修改全局变量
局部变量的定义
局部变量不能和全局变量同名,否则编译不通过
与javaScriptd对比
1.访问与修改
在javaScript中,与python一样,函数中可以对全局变量进行访问,但是不能修改
2.局部变量的定义
与pyhton相反,如果不加上关键字var ,则默认是全局变量,如果同名就直接顶替,必须加上关键字var才声明为局部变量
(在pyhton中是,不加关键字默认为局部变量,只有加上关键字global才是全局变量)
内嵌函数
python中支持在函数体内定义函数,作用范围限于函数体内
def fun1():
print ('fun1() is running!')
def fun2():
print('fun2() is running!')
fun1()
运行结果为
fun1() is running!
fun2() is running!
闭包
在上面已经提到,函数体内部可以访问全局变量,但是在外部却无法访问局部变量,而闭包就是提供了外部能够访问内部函数的变量和函数的一个入口,这点与javaScript中的闭包概念一样,有点类似于java类中提供的getset方法,而提供这个这么一个访问入口的函数,就称之为闭包
简单的说,闭包可以理解为"定义在一个函数内部的函数,提供了外部访问的入口"或者是"一个能够读取函数内局部变量的函数"
闭包的用途
1.上面提到的可以使得外部可以进行访问
2.既然可以供外部访问或是引用,那么这些局部变量就可以被保存到内存中,并且这些局部变量所依赖的函数,也同样的被保存了,不会被gc给回收掉。
下面是一个闭包的例子
def fun1(x):
def fun2(y)
return x * y
return fun2
fun3 = fun1(2) # 这里fun3获得了fun2的引用,成功的访问到了局部函数,所以fun2函数就是一个闭包
fun3(3) # 这里结果是 2 * 3 = 6
再一个例子
def fun1():
x = 5
def fun2():
nonlocal x # 在python2.x中,无法对外部变量进行修改,但在3.x中,引入nonlocal关键字,则可以进行修改,debug查看之后发现,外部变量确确实实的被改变了,不过我觉得这打破了函数体内不能拥有状态的这条性质....
x *= 5
return fun2()
fun2()# 运行结果为25
当然了这里的fun2()同样是一个闭包