Python教程
Python指南
-
终于知道为什么有中文字符的页面要设置编码格式为UTF-8了
python的条件判断语法:
if 条件1:
语句1
elif 条件2:
语句2
else:
语句3
注:(1)条件不能用括号括起来
(2)每个条件后面都需要有冒号,有点类似switch语句
- python的循环语法:
# -*- coding: utf-8 -*-
L = ['Bart', 'Lisa', 'Adam']
for name in L:
print("Hello,",name)
n=0
while n
注:(1)循环语法的条件后也需要有冒号
(2)语句没有结束符号(如JavaScript用分号结束)
(3)语句块也不要用大括号括起来
查找list的时间复杂度是O(n),查找dict的时间复杂度是O(1)。list是用时间换空间,dict是用空间换时间。
python的内置函数
Python中判断变量的类型有两种方法:isinstance()和type()。但是type()在判断的时候无法适用于子类,所以最好都用isinstance()去判断变量的类型。
Python中请使用isinstance()判断变量类型自定义异常用raise语句
函数的参数
(1)位置参数
def power(x,n):
s=1
while n>0:
n=n-1
s=s*x
return s
(2)默认参数
def power(x,n=2):
s=1
while n>0:
n=n-1
s=s*x
return s
(3)可变参数
def calc(*numbers):
sum=0
for n in numbers:
sum=sum+n*n
return sum
PS:定义完函数名后要加冒号哦,看来Python里面冒号很重要
(4)关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个truple。
而关键字参数允许你传入0个或任意个寒参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
def person(name,age,**kw):
print('name:',name,'age:',age,'other:',kw)
>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, city=extra['city'], job=extra['job'])
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
(5)命名关键字参数
用来限制关键字参数的名字,例如限定city和job作为关键字参数,定义如下:
def person(name,age,*,city,job):
print(name,age,city,job)
或者
def person(name, age, *args, city, job):
print(name, age, args, city, job)
(6)参数组合
对于任意函数,都可以通过类似func(*args,**kw)
的形式调用它,无论它的参数是如何定义的。
小结:
Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。
默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
要注意定义可变参数和关键字参数的语法:
args是可变参数,args接收的是一个tuple;
kw是关键字参数,kw接收的是一个dict。
以及调用函数时如何传入可变参数和关键字参数的语法:
可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过args传入:func((1, 2, 3));
关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过**kw
传入: func(**{'a': 1, 'b': 2})
。
使用*args
和**kw
是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。
命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。
定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符,否则定义的将是位置参数。
- 递归函数
如计算阶乘
def fact(n):
if n==1:
return 1
return n*fact(n-1)
使用递归函数需要注意防止栈溢出。在计算机中,函数是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多会导致栈溢出。可以试试fact(1000)
解决递归调用栈溢出的方法是通过尾递归优化,事实上,尾递归和循环的效果是一样的,所以把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指在函数返回的时候,调用自身且return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次都只占用一个栈帧,不会出现栈溢出的情况。
上面的递归求阶乘函数的尾递归话如下:
def fact(n):
return fact_iter(n,1)
def fact_iter(num,product):
if(num==1)
return product
return fact_iter(num-1,num*product)
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。
关于递归的联系题是汉诺塔问题,说实话,我从来就没弄懂过这个,不过这次学习Python倒是弄懂了,多亏了评论区的@大黑海豚reborn
汉诺塔思想笔记
认识汉诺塔的目标:把A柱子上的N个盘子移动到C柱子
递归的思想就是把这个目标分解成三个子目标
子目标1:将前n-1个盘子从a移动到b上
子目标2:将最底下的最后一个盘子从a移动到c上
子目标3:将b上的n-1个盘子移动到c上
然后每个子目标又是一次独立的汉诺塔游戏,也就可以继续分解目标直到N为1
代码:
def move(n,a,b,c):
if n==1:
print(a,'-->',c)
else:
move(n-1,a,c,b)#子目标1
move(1,a,b,c)#子目标2
move(n-1,b,a,c)#子目标3
n=input('enter the number:')
move(int(n),'A','B','C')
对了,有一句话说,所有的递归都可以用迭代实现。其实上面老师讲到的尾递归其实就是迭代。
计算fibonacci数列的三种方法
学习感悟:水平菜,但是我喜欢我的工作,我喜欢活到老学到老的IT行业。虽然工作中暂时用不到Python,但是我觉得学习一下没什么坏处,重点是,在学习的过程中可以夯实一下我那不太扎实的基础知识,毕竟像这些基础的语法和数据结构的思想是一致的嘛。我曾看到一位同事的签名:
读一些无用的书,做一些无用的事,花一些无用的时间,都是为了在一切已知之外,保留一个可以超越自己的机会。
我觉得很有道理。所以,等我把这个Python教程学完,下一个要学习的语言是PHP,嘿嘿。。。等等,为啥又是脚本语言???