廖雪峰笔记简单版

这篇博客详细介绍了Python的基础知识,包括数据类型(整数、浮点数、字符串、布尔值、空值)、变量、字符串操作、list、tuple、条件判断和循环。接着深入到函数、高阶特性如切片、迭代、列表生成式和生成器。还涵盖了函数式编程,如高阶函数、返回函数、匿名函数、装饰器和偏函数。在模块和面向对象编程部分,讲解了类、实例、继承、多态和访问限制。最后讨论了错误处理、调试和测试的基本方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

python基础

数据类型

  1. 整数:在程序中的表示方法和数学上一样。
  2. 浮点数:小数,数字很大时10用e表示,例如1.23×109要写成1.23e9。
  3. 字符串:用单引号’ 或双引号" 括起来的任意文本,如果字符串内部含有引号用转义字符即可(例如\’,转义字符\可以表示很多,\n表示换行,\t表示制表符,\本身也要转义,\\表示的字符是\)。
  4. 布尔值:True和False,可以用and,or,not计算。
  5. 空值:None,不可以理解为0,0是有意义的,而None就是空值。

变量

  1. 变量名必须是大小写英文、数字和_的组合,且不能用数字开头。
  2. 变量不仅可以是数字,还可以是任意数据类型。
  3. 常量就是不能变的变量,通常用全部大写的变量名表示常量。

字符串

  1. 在最新的Python3版本中,字符串是以Unicode编码的,即Python的字符串支持多语言。
  2. 字符串str,字节byte
  3. 格式化字符串,%s表示用字符串替换,%d表示用整数替换。如果不知道用什么,%s永远起作用,它会把任何数据类型转换为字符串。
  4. 编码内容太难了[哭]

list

  1. list是可变的有序集合,可以随时添加和删除其中的元素,可以往list中追加元素到末尾。
  2. len()函数可以获得list元素的个数,元素位置索引从0开始,最后一个是-1。
  3. append()函数可以追加元素到末尾。
  4. insert(i,p)函数可以插入元素p到任意位置i。
  5. pop(i)可以删除i位置的元素。
  6. list的元素也可以是另一个list。

tuple

  1. tuple一旦初始化就不能修改,也没有append(),insert()这样的方法,因为其不可变所以更安全,能使用tuple就不用list。
  2. 如果tuple里面包含一个list,虽然list不能指向到别的元素只能是list,但是list本身内容可变。
  3. 定义一个空的tuple,写成()。
  4. 定义一个只有1个元素的tuple,必须加一个逗号,例如t=(2,)只有一个元素2的tuple。

条件判断和循环

  1. 条件判断用if语句实现,要接冒号:,后面可以加elif做更细致的判断。
  2. 一种循环是for…in…循环,依次吧list或tuple里面的元素迭代出来。
  3. break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环。

dict和set

  1. dict字典,使用键-值(key-value)存储,查找速度非常快,一个key只能对应一个value,如果key不存在dict就会报错。
  2. 删除key用pop()的方式,其value也会一起删除。
  3. set和dict类似,也是一组key的集合,但不存储value,所以set中没有重复的key。
  4. add(key)方法可以添加元素到set中。
  5. remove(key)方法可以删除元素。

函数

  1. 调用函数:python中内置很多函数,知道函数的名称和参数就可以直接调用。
  2. 定义函数:定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
  3. 空函数:如果想定义一个什么事也不做的空函数,可以用pass语句,虽然pass语句什么都不做,但是可以用来当做占位符,
def nop():
    pass
  1. 参数检查:参数个数不对,系统可以自己检查,但是类型不对无法检查。
  2. 函数可以返回多个值,也就是tuple。
  3. 函数的参数除了正常的必选参数以外,还有默认参数、可变参数和关键字参数。默认参数就是把参数设置一个默认值,如果不输入其他值就是默认值。可变参数就是传入的参数个数可变,定义可变参数在参数前面加一个*即可,调用的时候不需要组装出一个list或者tuple。关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数,命名关键字参数必须传入参数名。
  4. 递归函数就是一个函数在内部调用自身本身,优点是定义简单逻辑清晰,缺点是存在栈溢出的问题(听不懂什么意思= =),可以通过尾递归防止栈溢出。
def person(name, age, *, city='Beijing', job):
    print(name, age, city, job)
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer

以上,*后面的city和job是关键字参数,其中city具有默认值,调用时可以不传入city的参数,输入engineer时必须同时输入参数名job。

高级特性

切片

  1. L[1:3]表示从索引1取到3(共两个),如果从索引0开始0可以省略L[:3],python支持倒数切片L[-2:]表示从倒数第二个取到最后,L[-2:-1]表示从倒数第二个取到倒数第一个(只有一个)。
>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
>>> L[0:3]
['Michael', 'Sarah', 'Tracy']
>>> L[:3]
['Michael', 'Sarah', 'Tracy']
>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']
  1. 如果L[:10:2]表示前10个每2个取一个,L[::5]表示所有的每5个取一个。

迭代

  1. 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)
  2. 一般情况下dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()。

列表生成式

  1. python内置的可以创建list的生成式
  2. 写列表生成式时,把要生成的元素放到前面,后面跟for循环,就可以把list创建出来,还可以使用两层循环(三层以上很少用)。

生成器generator

  1. 要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator。
  2. 可以通过next()函数获得generator的下一个返回值,但一般不会用next()而是用for循环进行迭代。
  3. 比较下面两个斐波拉契数列代码,第二个是generator,也就是说如果函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
  1. 生成器部分有点难…

函数式编程

高阶函数

  1. map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
  2. reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,效果就是reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
  3. filter()函数用于过滤序列
  4. sorted()函数可以对list进行排序,还可以接收一个key函数来实现自定义的排序

返回函数

匿名函数

  1. 关键字lambda表示匿名函数,冒号前面的x表示函数参数
  2. 用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突
  3. 匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数

装饰器

  1. 看不太懂

偏函数

  1. functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义

模块

使用模块

  1. python内置了很多模块,安装以后就可以使用很方便,导入模块用import语句。
  2. 正常的函数和变量名是公开的(public),可以被直接引用,有的函数我们希望只在模块内部使用而不给被人使用,通过下划线_前缀来实现,类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用。

安装第三方模块

  1. 在Python中,安装第三方模块,是通过包管理工具pip完成的
  2. 由于我装了pycharm这块就没仔细看 [尴尬]

面向对象编程(这部分好像有点难)

类和实例

  1. 类是抽象的模板,比如Student类
  2. 定义类是通过class关键字,class后面紧接着是类名,类名通常是大写开头的单词,如下定义了Student类
class Student(object):
    pass
  1. 定义好类以后,就可以创建实例,创建实例是通过类名+()实现的,下面bart就是student的一个实例
 bart = Student()
  1. 由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去(init前后有两个下划线
class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score

访问限制

  1. 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
  2. 接上,name,score属性,加上下划线以后就无法从外部访问bart.__name和bart.__score了
  3. 如果外部代码要获取name和score,可以给Student类增加get_name和get_score这样的方法
  4. 又要允许外部代码修改score,可以再给Student类增加set_score方法
class Student(object):
    ...

    def get_name(self):
        return self.__name
    def get_score(self):
        return self.__score
    def set_score(self, score):
        self.__score = score

继承和多态

  1. 当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)
  2. 继承有什么好处?最大的好处是子类获得了父类的全部功能,第二个好处需要我们对代码做一点改进
  3. 可以画一下继承树

获取对象信息

  1. 判断对象类型,使用type()函数
  2. isinstance()可以判断一个对象是否是该类型本身,或者位于该类型的父继承链上,还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是list或者tuple:
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
  1. 如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list

实例属性&类属性

  1. 给实例绑定属性的方法是通过实例变量,或者通过self变量
  2. 当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到
  3. 在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性
>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

面向对象高级编程

使用__slots__

  1. 正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性
  2. 如果我们想要限制实例的属性,可以在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性
  3. __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

使用@property

  1. 可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性
  2. 具体怎么用没太看懂 [捂脸]

多重继承

通过多重继承,一个子类就可以同时获得多个父类的所有功能

定制方法

Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类,详情参见python官网文件定制方法

枚举类和元类

  1. 枚举类
  2. metaclass直译为元类,先定义metaclass,就可以创建类,最后创建实例,因此metaclass允许你创建类或者修改类
  3. 这块要再看看==

错误、调试和测试

错误处理

  1. 在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原因
  2. python内置了一套try…except…finally…的错误处理机制
  3. 当我们认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕。
  4. 如下给出一个例子:
try:
    print('try...')
    r = 10 / 0
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
finally:
    print('finally...')
print('END')
  5. 出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置。
  1. 记录错误
  2. 抛出错误

调试

  1. 出现错误后,第1种方法就是用print()来检查错误,但坏处是以后还要删除
  2. 第2种方法是用断言assert来替代,例如下面assert的意思是,表达式n != 0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错。assert的好处后期可以启动Python解释器,用-O(大写字母O)参数来关闭assert。
def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'
    return 10 / n

def main():
    foo('0')
  1. 第3种方式是把print()替换为logging,logging不会抛出错误而且可以输出到文件,logging.info()就可以输出一段文本(logging是终极武器,比较好用
import logging

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
  1. 第4种方式是启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态,但是略麻烦。
  2. 第5种方法是在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点,
  3. 最后一个是IDE功能,可以比较爽地设置断点、单步执行

单元测试

  1. 编写单元测试需要引入Python自带的unittest模块

文档测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值