一.模块
①在Python中,一个.py文件就称之为一个模块(Module)
②使用模块可以避免函数名和变量名冲突,同名的函数和变量完全可以分别存在于不同的模块中,但是要注意,避免与内置函数名发生冲突。

③如果不同的人编写的模块名相同怎么办?
- 为了避免模块名冲突,
Python引入了按目录来组织模块的方法,称之为包(package)。

1.使用模块
①
#让该脚本/模块文件在Unix/Linux/Mac上运行
#!/usr/bin/env python3
#表示脚本/模块本身使用标准UTF-8编码
# -*- coding: utf-8 -*-
#任何模块代码的第一个字符串均表示模块的文档注释
'a test module'
#使用__author__变量把作者写进去
__author__ = 'Gerg'
#导入sys模块后,就有了变量sys指向该模块
#通过sys这个变量,就可以访问sys模块的所有功能
import sys
def test():
#sys模块有一个argv变量,用list存储了命令行的所有参数
#argv至少有一个参数,因为第一个参数永远是该.py文件的名称
args = sys.argv
if len(args) == 1:
print('Hello,world!')
elif len(args) == 2:
print('Hello,%s' %args[1])
else:
print('Too mant arguments!')
#当我们直接运行该模块文件时,Python解释器把一个特殊变量
#__name__置为__main__;但如果在其他地方导入该模块时,
#if判断将失败。运行测试
if __name__ == '__main__':
test()

①.py文件有两种使用的方式:第一种是直接作为脚本运行;另一种是import到其他python脚本中被调用(模块重用)执行。
②if __name__ == ''__main___":只有在第一种情况下(即文件作为脚本直接执行)才会被执行。


③运行的原理


- 注:每个
python模块(脚本,这里就是test.py和import_test.py)都包含内置的变量__name__,当模块被直接运行时,__name__等于文件名(包含后缀.py);如果import到其他模块中,则__name__等于模块名(不包含后缀.py)。而"__main__"等于当前执行文件的名称(包含了后缀.py)。
2.作用域
①正常的函数和变量名都是公开的(public),可以被直接引用。
②类似__xxx__这样的变量是特殊变量,可以被直接引用,但有特殊的用途。
③类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用。
④外部不需要引用的函数全部定义为private,只有外部需要引用的函数才定义为public。
3.安装第三方模块
①在Python中,安装第三方模块,是通过包管理工具pip完成的。
二.面向对象编程(Object Oriented Programming)
①把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
②什么是面向过程的程序设计?
- 把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为若干子函数。
③什么是面向对象的程序设计?
- 把计算机程序视为一组对象的集合,每个对象都可以接收其他对象发送过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
④在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
⑤面向过程和面对对象在程序流程上的不同?
- 面向过程:

- 面向对象:(给对象发消息,实际上就是调用对象对应的关联函数,称之为方法
(Method))

面向对象的设计思想是抽离出
Class,根据Class创建Instance。面向对象的抽象程序要比函数更高,因为一个
Class既包含数据,又包含了操作数据的方法。面向对象的三大特点:数据封装、继承和多态
1.类(Class)和实例(Instance)
①如何创建实例?

②由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去。
class Student(object):
#__init__方法的第一个参数永远是self,表示创建的实例本身。
#有了__init__方法,在创建实例的时候,就不能传入空的参数了
#必选传入与__init__方法匹配的参数,但self不需要传。
def __init__(self,name,score):
self.name = name
self.score = score

2.数据封装
①在Student类中,每个实例都拥有各自的name,score这些数据,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样,就把"数据"封装起来了。这些封装数据的函数和Student类本身是由关联的,因此,我们称之为类的方法。

②封装的另一个好处是可以给Student类增加新的方法,如何get_grade:

3.小结
①类是创建实例的模板,而实例则是一个一个具体的对象,每个实例拥有的数据互相独立、互不影响。
②方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据。
4.访问限制
①虽然将数据和操纵数据的方法都封装进一个类中,但仍可以通过外部代码自由修改一个实例的name、score属性:

②如何做到内部属性不被外部访问?
- 可以在属性的名称前加上两个下划线
__

③但是如果外部代码要获取name和score怎么办?

④如果又想允许外部代码修改score怎么办?

⑤其实双下划线开头实例变量不一定不能从外部访问,不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,可以通过_Student__name来访问__name变量(强烈不建议那么干,因为不同版本的Python解释器会把__name改成不同的变量名)

⑥一个大坑:

- 注:其实这个
__name变量和Class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给person1新增了一个__name变量。

5.继承和多态
①在OOP程序设计中,当我们定义一个Class时,可以从某个现有的Class继承,新的Class称之为子类(Subclass),而被继承的Class称为基类、父类或超类(Base Class、Super Class)。

- 注:对于
Dog来说,Animal就是它的父类;对于Animal来说,Dog就是它的子类。
②继承有什么好处?
- 最好的好处是子类获得了父类的全部功能。
③当子类和父类存在相同的run()方法时,子类的run()会覆盖了父类的run(),在代码运行的时候,总会调用子类的run()。这样,我们就获得了继承的另一个好处:多态。

④当我们定义一个Class的时候,实际上我们就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没有什么两样。
a = list() #a是list类型
b= Animal() #b是Animal类型
c = Dog() #c是Dog类型
- 如何判断一个变量是否是某个类型?
isinstance()

⑤对于一个变量,我们只需知道它是Animal类型,无需确切地知道它的子类型,就可以放心调用run()方法,而具体调用的run()方法是在Animal、Dog、Cat还是Wangba对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节。

⑥什么是"鸭子类型"?
它并不要求严格的继承体系,一个对象只要"看起来像鸭子,走起路来像鸭子",那它就可以被看做鸭子。
对于静态语言,如果需要传入
Animal类型,则传入的对象必须是Animal类型或它的子类,否则,就无法调用run()方法。对于
Python这样的动态语言,则不一定需要传入Animal类型,只需保证传入的对象由一个run()方法就可以了。
6.获取对象信息
①如何判断对象的类型?
-
type()函数 - 返回对象Class类型

②如果要判断一个对象是否是函数怎么办?
- 可以使用
types模块中定义的常量(FunctionType,BuiltinFunctionType,LambdaType,GeneratorType)

③isinstance()

④dir() - 获取一个对象的所有属性和方法。

⑤配合getattr()、setatter()和hasattr(),可以直接操作一个对象的状态。

⑥也可以获得对象的方法(赋值给一个变量)。

7.实例属性和类属性
①实例属性

②类属性

③不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性时,再使用相同的名称,访问的将是类属性。
三.面向对象高级编程
1.使用__slots__(卡槽)
①有什么用?
- 限制实例的属性。

②__slots__定义的属性只对当前类实例起作用,对继承的子类是不起作用滴。

2.使用@property
①在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没有办法检查参数,导致一些神奇的操作:
s = Student()
s.score = 9999
②为了限制score的范围,可以通过set_score()方法来设置成绩,再通过get_score()方法来获取成绩。


③有没有既能检查参数,又能用类似属性这样简单的方式来访问类的变量呢?
-
Python内置的@property装饰器就是负责把一个方法变成属性调用的。


