Python学习笔记基础篇

来源:互联网 发布:java面试逻辑题及答案 编辑:程序博客网 时间:2024/05/16 18:20


博客内容都是从《廖雪峰官方网站》Python教程收集http:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000;


一、使用文本编辑器
(1)不能使用Word和windows自带的记事本;Word保存的不是纯文本文件,而记事本会自动在文件开始的地方记上几个特殊字符(UTF-8);
(2)Python文件必须以.py结尾,文件名只能是英文字母、数字、下划线组成个;
(3)命令行模式和Python交互模式:
命令行模式:可以执行python进入Python交互式环境,也可以执行python文件;
交互式环境:会把每一行Python代码的结果自动打印出来;
(4)直接运行py文件
在windows上不行,但在Mac和Linux上是可以的,方法是在py文件的第一行加上一个特殊的注释:#!/usr/bin/env python3
(5)直接输入python进入交互模式,相当于启动了python解释器,但是等待你一行一行地输入源代码,每输入一行就执行一行;
(6)直接运行py文件相当于启动了python计时器,然后一次性把py文件的源代码给执行了;
(7)使用代码运行助手:可以让你在线输入Python代码,然后通过本机运行的一个Python脚本来执行代码;


二、输入和输出
(1)输出:print()函数可以接受多个字符串,用逗号隔开“,”;遇到逗号会输出一个空格;
(2)输入:input(),输入类型是数值类型或者字符串类型,返回的是字符串类型数据;


三、Python语法基础
(1)#开头的语句是注释;
(2)每一行都是一个语句,当语句以冒号":"结尾时,缩进的语句视为代码块,按照约定俗称的管理,应该始终坚持使用4个空格的缩进;
(3)Python程序是大小写敏感的;


四、数据类型
(1)数据类型:整数、浮点数、字符串、布尔值(True、False、0或非0、and、or、not)、空值(None)、变量(动态语言);


五、字符串编码
(1)python3 字符串使用 Unicode,直接支持多语言;
(2)str和bytes互相转换时,需要指定编码。最常用的编码是UTF-8。python当然也支持其他编码方式,如GB2312;


六、使用list和tuple
(1)list:一种有序的集合,可以随时添加和删除其中的元素;
(2)list初始化:classmates = ["Allen", 1, Ture]
(3)list访问:可以通过索引访问(classmates[1]),也可以倒叙获取(classmates[-1]);
(4)list数组越界;
(5)list删除元素:删除末尾元素(classmates.pop()),删除指定位置元素(classmates.pop(1));
(6)list元素替换元素:classmates[1] = "Sarah";
(7)list元素也可以是list,二位数组;
(8)list拼接元素到最后一个位置:append();
(9)list插入元素到指定位置:insert();
【1】tuple:一种有序列表,跟list非常相似,但是一旦初始化就不能修改;
【2】tuple初始化:name = ("Michael", "Bob", "Baby");
【3】tuple访问:name[0],name[-1];
【4】tuple不可变,代码更安全,可以用tuple替代list就尽量用tuple;
【5】tuple陷阱:定义tuple时,tuple元素就必须要确定下来;tuple=(1),tuple只有1个元素的时候,要加上“,”,tuple=(1,);
【6】tuple元素不可能变化:必须保证tuple的每一个元素本身不能变,如(tuple=("1", 1, ["1"]));


七、条件判断
(1)if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>
(2)再议input
input()获取返回的数据类型是字符串,字符串不能直接和整数比较,必须先把字符串类型转换成整数类型,int();

八、循环
(1)for name in names:;
(2)while name>0: ;


九、使用dict和set
(1)dic:使用键值对存储,具有极快的查找速度,无论表有多大,查找速度都不会变慢;
(2)dic初始化:d = {"Michael":95, "Bob":34, "Baby":43};
(3)dic访问和数据替换:d["Baby"]、d["Baby"]=23,多次对一个key放入value,后面的值会把前面的值替换;
(4)dic判断key是否存在:"Baby" in d、 d.get("Baby")返回布尔值,或者自己指定返回的value:d.get("Baby", -1);
(5)删除key:d.pop("Baby");
(6)dic内部存放的顺序和key放入的顺序是没有关系的;
(7)和list比较dic有特点:查找和插入的速度极快,不会随着key的增加而变慢;需要占用大量的内容,内存浪费多;
(8)list有特点:查找和插入的时间随着元素的增加而增加;占用空间小,浪费内存小;
(9)dict重要;dic的key必须是不可变对象,list是可变的,不能作为key使用;
【1】set:和dict类似,也是一组key的集合,但不存储value,由于Key不能重复,所以在set中,没有重复的key;
【2】set初始化:需要提供一个list作为输入集合,s = set([1, 2, 3]);
【3】set:重复元素在set中自动被过滤掉;
【4】set添加:通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果;
【5】set删除:通过remove(key)方法可以删除元素;
【6】set和dict的唯一区别仅在于没有存储对应的value,set的原理和dict一样,因此同样不可以放入可变对象;




十、定义函数
(1)定义函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号":",在缩进块中编写函数体,函数的返回值用return语句返回;
(2)一旦执行到return时,函数就执行完毕,并将结果返回;
(3)如果没有return语句,函数执行完毕后也会返回结果,只是结果为None,return None 可以简写为return;
(4)空函数:如果想定义一个什么都不做的空函数,可以用pass语句,可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass;缺少pass,代码运行就有语法错误;
(5)返回多个值:函数可以返回多个值,返回的值是一个tuple,在return语句中,tuple允许省略中括号();


十一、函数的参数
(1)默认参数初始化:def power (x, y=3);
(2)默认参数:必须参数在前,默认参数在后,否则Python的解释器会报错;
(3)默认参数:当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面,变化小的参数可以作为默认参数;
(4)默认参数:最大的好处是能降低调用函数的难度(限制);
举例:def enroll(name, gender, age=6, city='Beijing'):
可以不按顺序提供部分默认参数,当不按顺序提供部分默认参数时,需要吧参数名写上;
举例:enroll('Adam', 'M', city='Tianjin');
(5)默认参数:牢记一点,默认参数必须指向不变对象(None和str);
【1】可变参数:传入函数的参数个数可变,可以是任意多个,还可以是0个;
【2】可变参数:定义可变参数和定义list或tuple参数相比,仅仅在参数前面加个*号;
【3】可变参数:个人理解,可变参数整体可以看作一个list,可变参数中,每个参数就是list或者tuple中的每个元素,可以是任意多的元素,也可以是0个参数;
【4】可变参数:在list或tuple前面加一个*号,把list或tuple的每个元素变成可变参数传进去;
【5】可变参数:可变参数允许传入0个或任意多个参数,这些可变参数在函数调用时自动组装为一个tuple;
<1>关键字参数:允许传入0个或任意多个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict;
举例:def person(name, age, **kw):函数除了必须参数name和age外,还接受关键字参数kw,kw参数可以是任意多个或0个值;
<2>关键字参数:可以扩展函数的功能。比如person函数里,保证接收到name和age两个参数,但是如果调用者愿意提供更多的参数也可以收到;
举例:用户注册,除了name和age参数必填,其他参数选填;
<3>关键字参数:可以把该dict转换为关键字参数转进去;
举例:person('Jack', 24, city=extra['city'], city='Beijing');
输出:name: Bob age: 35 other: {'city': 'Beijing'};
举例:extra = {'city': 'Beijing', 'job': 'Engineer'},person('Jack', 24, city=extra['city'], job=extra['job']);
输出:name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
举例:extra = {'city': 'Beijing', 'job': 'Engineer'},person('Jack', 24, **extra);
输出:name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
**extra表示吧extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra;
【1】命名关键字参数:如果要限制关键字参数的名字,可以用命名关键字参数,例如只接受city和job作为关键字参数,这种方式定义的参数如下:
举例:def person(name, age, *, city, job):
命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数;
【2】命名关键字参数:可以有省略值,从而简化调用:
举例:def person(name, age, *, city='Beijing', job):
由于命名关键字参数city具有默认值,调用时,可不传入city参数;
举例: person('Jack', 24, job='Engineer')
【3】命名关键字参数:特别注意,*不是参数,而是特殊分隔符。如果缺少*,Pythob解释器将无法识别位置参数和命名关键字参数(缺少*,city和job被视为位置参数);
总结:参数组合,参数定义的顺序必须是 必选参数、默认参数、可变参数/命名关键字参数和关键字参数;


十二、切片
(1)取前N个元素L[n:m],L是对象名称(list或tuple),n是起始位置,m是结束位置。获取的是从n到m(不包括m)位置的数据,个数是m-n个;
举例:L[0:3],获取第0个位置数据,第1个位置数据,第2个位置数据;
举例:L[-2:0]或者L[-2:],获取倒数第二个数据,倒数第一个数据;
(2)前10个数,每两个取一个:L[:10:2];
(3)所有数,每5个数取一个:L[::5];
(4)原样复制一个list:L[:];
(5)tuple也是一种list,区别是tuple不可变,所以也可以用切片操作;
(6)字符串也可以看成是一种list,每个元素就是一个字符,字符串也可以用切片操作;


十三、迭代
(1)如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代;
(2)dict迭代,因为dict的存储不是按照list的方式顺序排列,所以迭代出的结果顺序可能不一样;
举例: d = {'a': 1, 'b': 2, 'c': 3},for key in d:(遍历key);
举例:for value in d.values()(遍历values);
举例:for k, v in d.items()(遍历key和value);
(3)字符串迭代;
(4)判断对象是否迭代对象,是否可以迭代:
举例:from collections import Iterable;
举例:isinstance('abc', Iterable) # str是否可迭代(结果为布尔值);
举例:isinstance([1,2,3], Iterable) # list是否可迭代(结果为布尔值);
(5)对list实现下标循环,使用内置的enumerate函数;
举例: for i, value in enumerate(['A', 'B', 'C']):(索引-元素对)
举例: for x, y in [(1, 1), (2, 4), (3, 9)]:
(6)自定义数据类型也可以通过for循环迭代;
【1】列表生成式:Python内置的非常简单却强大的可以用来创建list的生成式,list(range(10, 100));
【2】列表生成式:一层循环,[x * x for x in range(10, 100)];
【3】列表生成式:二层循环,[x * y for x in "abc" for y in "123"];


十四、函数式编程
(1)函数式编程就是一种抽象程序很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此任意一个函数,只要输入是确定的,输出就是确定的;
(2)函数式编程:允许把函数本身作为参数传入另一个函数,允许返回一个函数!
(3)Python不是纯函数式编程语言;


十五、高阶函数
(1)变量可以指向函数;函数本身可以赋值给变量,变量可以指向函数;
(2)函数名也是变量:函数名其实就是指向函数的变量;
(3)传入函数:变量可以指向函数,函数的参数可以接收变量,那么函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数;
(4)高阶函数:一个函数可以接收另一个函数作为参数,函数式编程就是指这种高度抽象的编程范式;
【1】map():map()函数可以接收两个参数,一个是函数,一个是Iterable(迭代),map将传入的函数一次作用到序列的每个元素,并把结果作为新的Iterator(迭代器)返回;
【2】reduce():把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累计计算;
【3】filter():和map()类似,filter()一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素;
【4】sorted():一个高阶函数,用sorted()排序的关键在于实现一个映射函数;


十六、返回函数
(1)函数作为返回值:高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回;
举例:def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
————在这个例子中,我们在函数 lazy_sum 中又定义了函数sum,并内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回函数中,这种称为”闭包“的程序结构拥有极大的威力;
————当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数;(因为函数名指向的函数地址不同)
(2)闭包:当一个函数返回了一个函数后,其内部的局部变量还被新函数引用;
举例:def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs


f1, f2, f3 = count()

十七、匿名函数


十八、装饰器


十九、偏函数


二十、模块


二十一、使用模块


二十二、安装第三方模块


二十三、面向对象编程
(1)在Python中,所有的数据类型都可以视为对象,也可以自定义对象,自定义的对象数据类型就是面向对象中的类的概念;
(2)成员方法,属性; 
(3)封装、继承、多态;


二十四、类和实例
面向对象最重要的概念就是类和实例,必须牢记类是抽象的模板,而实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法,但各自的数据可能不同;
(1)定义类是通过class关键字,class后面紧接着是类名,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,如果没有合适的继承类,就是用object类;
(2)类创建实例对象:类名+()实现;
(3)类的属性不需要定义,直接使用就可以了;
(4)__init__:通过这个方法,可以在创建实例对象的时候,绑定一些属性填写进入;
举例:class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
————第一个参数永远是self,表示创建的实例本身,因此在方法内部,可以把各种属性绑定到self,因为self就指向创建的实例本身;
————创建实例对象:student = Student("Allen", 40);
————有了__init__方法,在创建实例的时候,就不能传入空的参数,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进入;
(5)数据封装:创建类,类中创建方法(类方法),通过类创建实例对象,实例对象访问数据;
举例:class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
bart.print_score()
————创建实例需要给name和score;
(6)和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然他们都是同一个类的不同实例,但拥有的变量名称都可能不同;


二十五、访问限制
(1)私有变量:只有类内部可以访问,变量名以__开头;
(2)如果外部代码要获取私有变量,可以给类增加 get_name 和 get_score 这样的方法;
(3)如果外部代码要修改私有变量,可以给类增加 set_name 和 set_score 这样的方法;
(4)在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,是可以直接访问的,不是private变量,所以不能用__name__、__score__这样的变量名;
(5)以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是按照约定俗成的规定,当你开导这样的变量时,意思是,虽然我可以被访问,但是请把我视为私有变量,不要随意访问;
(6)双下划线开头的实例变量是不是一定不能从外部访问呢?其实不是,不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量;


二十六、继承和多态
(1)继承:子类继承父类所有的公有属性跟方法(私有属性无法继承);
(2)子类对父类方法重写;
(3)判断一个变量是否是某个类型可以用 isinstance(对象名, 类名) 判断;
(4)多态:对扩展开放,允许新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run_twice()等函数;
(5)静态语言vc动态语言:对于静态语言来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则将无法调用run()方法;
对于Python这样的动态语言来说,则不一定需要传入Animal类型,我们只需要保证传入的对象有一个run()方法就可以了;
这就是动态语言的”鸭子类型“,它并不要求严格的继承体系,一个对象只要”看起来像鸭子“,他就可以被看成是鸭子;
(6)如果父类定义了__init__方法,则子类必须显示地调用父类的__init__方法,如果子类要扩展父类的行为,可以添加__init__方法的参数;


二十七、获取对象信息
(1)获取对象的数据类型:type(对象名),前提是变量指向函数或者类,返回的是对应的class类型;
(2)判断class的类型,可以使用isinstance(对象名,类名)函数,判断对象是否属于该类;
(3)获取一个对象的所有属性和方法,可以使用dir(对象名)函数,返回一个包含字符串的list;
(4)类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度;
(5)判断是否有属性:hasattr(对象名,属性名称"字符串");
(6)设置一个属性:setattr(对象名,属性名称"字符串");
(7)获取一个属性值:getattr(对象名,属性名称"字符串");
————如果属性不存在,会抛出AttributeError的错误;
————可以传入一个default参数,如果属性不存在,就返回默认值:getattr(obj, "z", 404);


二十八、实例属性和类属性
(1)由于Python是动态语言,根据类创建的实例可以任意绑定属性;
(2)如果类需要绑定一个属性,可以直接在类中定义属性,这种属性是类属性,通过 类名.属性名 ,可以访问类属性;
举例:>>> 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的实例后,我们可以给该实例绑定任何属性和方法,这是动态语言的灵活性;
举例:class Student(object):
pass
>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>> print(s.name)
Michael
>>> def set_age(self, age): # 定义一个函数作为实例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25
————给一个实例绑定方法,对另一个实例是不起作用的;
(2)给所有实例都绑定方法:
举例:>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = MethodType(set_score, Student)
(3)使用__slots__:限制实例的属性,比如只允许对Student实例添加或者访问name和age属性;
举例:class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
(4)注意:__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的,除非在子类中也定义__slots__,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__;
(5)@property:


三十、多继承
(1)多继承:class 子类名(父类名, 父类名, 父类名....);
(2)在设计类的继承关系时,主线都是单一继承下来的。但是如果需要额外的功能,通过多重继承就是实现,这种设计通常称之为MixIn;
为了更好地看出继承关系,把Runnable和Flyable改为RunnableMixIn和FlyableMinxIn;
MixIn的目的就是给一个类增加多个功能,这样在设计类的时候,我们优先考虑通过多继承来组合多个MixIn的功能,而不是设计多层次的复杂继承关系;


三十一、定制类
(1)





0 0