一.模块
①在Python
中,一个.py
文件就称之为一个模块(Module)
②使用模块可以避免函数名和变量名冲突,同名的函数和变量完全可以分别存在于不同的模块中,但是要注意,避免与内置函数名发生冲突。
所有内置函数.png③如果不同的人编写的模块名相同怎么办?
- 为了避免模块名冲突,
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()
1.png
①.py
文件有两种使用的方式:第一种是直接作为脚本运行;另一种是import
到其他python
脚本中被调用(模块重用)执行。
②if __name__ == ''__main___"
:只有在第一种情况下(即文件作为脚本直接执行)才会被执行。
③运行的原理
加个print__name__直接运行脚本.png 第二种方法.png- 注:每个
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)
①如何创建实例?
类型+()创建实例.png②由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__
方法,在创建实例的时候,就把name
,score
等属性绑上去。
class Student(object):
#__init__方法的第一个参数永远是self,表示创建的实例本身。
#有了__init__方法,在创建实例的时候,就不能传入空的参数了
#必选传入与__init__方法匹配的参数,但self不需要传。
def __init__(self,name,score):
self.name = name
self.score = score
__init__.png
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
改成不同的变量名)
⑥一个大坑:
大坑.png- 注:其实这个
__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()
,可以直接操作一个对象的状态。
⑥也可以获得对象的方法(赋值给一个变量)。
获得对象的方法.png7.实例属性和类属性
①实例属性
实例属性.png②类属性
类属性.png③不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性时,再使用相同的名称,访问的将是类属性。
三.面向对象高级编程
1.使用__slots__
(卡槽)
①有什么用?
- 限制实例的属性。
②__slots__
定义的属性只对当前类实例起作用,对继承的子类是不起作用滴。
2.使用@property
①在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没有办法检查参数,导致一些神奇的操作:
s = Student()
s.score = 9999
②为了限制score
的范围,可以通过set_score()
方法来设置成绩,再通过get_score()
方法来获取成绩。
③有没有既能检查参数,又能用类似属性这样简单的方式来访问类的变量呢?
-
Python
内置的@property
装饰器就是负责把一个方法变成属性调用的。
网友评论