Python学习笔记(一)

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,嘿嘿。。。等等,为啥又是脚本语言???

你可能感兴趣的:(Python学习笔记(一))