快乐学习
前程无忧、中华英才非你莫属!

Python3基础精简版

 

前言

 

非常感谢廖雪峰老师的免费开源的Python3教程:因为教程实在写的太好了!

花了点时间将廖老师的文章,调整、排序,浓缩 ,以便于对于掌握其它编程语言的小伙伴快速上手Python3!

原教程地址:https://www.liaoxuefeng.com/ 作者:廖雪峰

 


 

一、介绍

 

Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。

在Windows上安装Python

首先,根据你的Windows版本(64位还是32位)从Python的官方网站下载Python 3.6对应的64位安装程序32位安装程序(网速慢的同学请移步国内镜像),然后,运行下载的EXE安装包。

 

Python解释器:当我们编写Python代码时,我们得到的是一个包含Python代码的以.py为扩展名的文本文件。要运行代码,就需要Python解释器去执行.py文件。*(官方版本:cPython)


 

二、数据结构:

整数、浮点数、字符串、布尔值、空值(none)、变量、常量。

list :[ ]   列表  、 set:([]) 不重复无序的集合、tuple:( ) 不可变列表   dict:{ } 字典、相当于java中的map。

 


 

三、函数

 

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”

def sum(x):
  pass

 

说是可以返回多个值,返回的仍然是单一值:只是返回了一个tuple!

https://docs.python.org/3/library/functions.html 内置函数参考

 


四、参数:

 

def person(*age): 可变参数、是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数

 

def person(name, age, **kw):关键字参数,允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict:

 

 

def person(name, age, **kw): 

print('name:', name, 'age:', age, 'other:', kw)

>>> person('Adam', 45, gender='M', job='Engineer') 

name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}

>>> person('Jack', 24, **extra) name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

 

def person(name, age, *, city, job):如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。

 

>>> person('Jack', 24, city='Beijing', job='Engineer') 
Jack 24 Beijing Engineer

 

 

def person(name, age=2):默认参数。

def person(name, age):必选参数。

 

参数组合:参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

五、迭代
默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()。
for 循环变量 in  要被遍历的内容':
那么,如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断

 

六、列表生成式

即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式
[[x * x for x in range(1, 11)]]

 

 


 

 

 

七、生成器

 

一边循环一边计算的机制,从从而节省大量的空间而节省大量的空间,称为生成器:generator。

 

创建一个generator,有很多种方法。

 

第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

 

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

 

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

>> isinstance(iter('abc'), Iterator)
True

 

八、函数式编程

 

一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数!

def add(x, y, f):
    return f(x) + f(y)

 

 

 

 

九、重要函数讲解

 

map/reduce函数:
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回~

 

把这个list所有数字转为字符串:

>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

 

 

reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算

 

>>> from functools import reduce
>>> def add(x, y):
......... return x + y
>>> reduce(add, [1, 3, 5, 7, 9])
25

 

filter函数

Python内建的filter()函数用于过滤序列。

 

 

sorted函数

Python内置的sorted()函数就可以对list进行排序。

 

偏函数

在介绍函数参数的时候,我们讲到,通过设定参数的默认值,可以降低函数调用的难度。而偏函数也可以做到这一点
>>> import functools
>>> int2 = functools.partial(int, base=2)    转换成二进制的整数
>>> int2('1000000')
64

 

 

type函数

既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义:
要创建一个class对象,type()函数依次传入3个参数:
  1. class的名称;
  2. 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
  3. class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。
>>> def fn(self, name='world'): # 先定义函数
... print('Hello, %s.' % name)
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>

 

 


 

 

 

十、闭包:

这种在函数中定义函数,又定义了函数,叫闭包,并让定义函数作为返回值,不需要立刻求值,而是在后面的代码中,根据需要再计算。

 

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量

 

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:


十一、匿名函数:
关键字lambda表示匿名函数,冒号前面的x表示函数参数,匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

十二、装饰器:
代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
@log('execute')
def now():
print('2015-3-25')
把@log放到now()函数的定义处,相当于执行了语句:
>>>now = log(now)
装饰器也是可以传入参数的:
@log('execute')
def now():
print('2015-3-25')
相当于:>>> now = log('execute')(now)


十三、模块

import sys

 

说明结尾两行代码:

if __name__=='__main__':
test()

 

当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该hello模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。

 

我们可以用命令行运行hello.py看看效果:

$ python3 hello.py
Hello, world!
$ python hello.py MichaelHello, Michael!

 

十四、作用域

类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc,__abc等;

 

我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,即:

外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。

 

十五、类

类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。

通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑

上去:

类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类
定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:
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))

 

注意:Student().name 是外部实例变量不等于Class Student 的内部name属性。


 

十六、继承和多态

 

class Dog(Animal):  Animal为父类,这就是继承

   pass

 

多重继承:直接在小括号里,继承多个类就行了~

class Dog(Mammal, Runnable): Mammal, Runnable为两个父类,
   pass

 

高级编程语言多态都是一个概念,python也不例外,重写父类的方法就是多态!


 

十七、实例属性和类属性

s.set_age = MethodType(set_age, s) # 给实例绑定一个方法,在新建一个实例就不生效了。下面还可以为class绑定方法,

 

这样在新建实例也可以生效了!

>>> def set_score(self, score):
... self.score = score
>>> Student.set_score = set_score

 

限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性:

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
__str__:类似于java中的重写toString方法,python 在调用print方法的时候,会执行你定义的~

 

__iter__:如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环

 

__getitem__:实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,要表现得像list那样按照下标取出元素,需要实现__getitem__()方法

 

__getattr__:调用不存在的score属性,就有问题了:要避免这个错误,除了可以加上一个score属性外,Python还有另一个机制,那就是写一个__getattr__()方法,动态返回一个属性,返回函数也是完全可以的。

 

__call__:任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用


 

十八、枚举类

 

Enum可以把一组相关常量定义在一个class中,且class不可变,而且成员可以直接比较。


 

十九、metaclass(元类)

除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。
metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况,所以,以下内容看不懂也没关系,因为基本上你不会用到。
metaclass可以给我们自定义的MyList增加一个add方法:
# metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)
有了ListMetaclass,我们在定义类的时候还要指示使用ListMetaclass来定制类,传入关键字参数metaclass:
class MyList(list, metaclass=ListMetaclass):
pass
当我们传入关键字参数metaclass时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。
__new__()方法接收到的参数依次是:
  1. 当前准备创建的类的对象;
  2. 类的名字;
  3. 类继承的父类集合;
  4. 类的方法集合。
测试一下MyList是否可以调用add()方法:
>>> L = MyList()
>>> L.add(1)
>> L
[1]
而普通的list没有add()方法:
>>> L2 = list()
>>> L2.add(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'add'
动态修改有什么意义?直接在MyList定义中写上add()方法不是更简单吗?正常情况下,确实应该直接写,通过metaclass修改纯属变态。

二十、异常处理
高级语言通常都内置了一套try...except...finally...的错误处理机制,Python也不例外。
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')

调用栈

如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。来看看err.py:
# err.py:def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar('0')
main()
执行,结果如下:
$ python3 err.py
Traceback (most recent call last):
File "err.py", line 11, in <module>
main()
File "err.py", line 9, in main
bar('0')
File "err.py", line 6, in bar
return foo(s) * 2
File "err.py", line 3, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
出错并不可怕,可怕的是不知道哪里出错了。解读错误信息是定位错误的关键。我们从上往下可以看到整个错误的调用函数链:
错误信息第1行:
Traceback (most recent call last):
告诉我们这是错误的跟踪信息。
第2~3行:
File "err.py", line 11, in <module>
main()
调用main()出错了,在代码文件err.py的第11行代码,但原因是第9行:
File "err.py", line 9, in main
bar('0')
调用bar('0')出错了,在代码文件err.py的第9行代码,但原因是第6行:
File "err.py", line 6, in bar
return foo(s) * 2
原因是return foo(s) * 2这个语句出错了,但这还不是最终原因,继续往下看
File "err.py", line 3, in foo
return 10 / int(s)
原因是return 10 / int(s)这个语句出错了,这是错误产生的源头,因为下面打印了:
ZeroDivisionError: integer division or modulo by zero
根据错误类型ZeroDivisionError,我们判断,int(s)本身并没有出错,但是int(s)返回0,在计算10 / 0时出错,至此,找到错误源头

出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置。

抛出错误

如果要抛出错误,首先根据需要,可以定义一个错误的class,选择好继承关系,然后,用raise语句抛出一个错误的实例:

 

 

待续

 

打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Python3基础精简版

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!