二 程序设计与数据结构
1 万物皆对象、Python不例外
1.1 面向对象编程基本概念:
- Python从设计之初就已经是一门面向对象的语言,比如Java, C#, Javascript,C++都是典型的面向对象语言.C语言和汇编语言是典型的面向过程语言.
- 面向过程的语言更倾向于功能的实现与封装,体现计算机实现功能
- 面向对象的语言更倾向于业务层面的流程实现,体现解决具体事物流程
- 现代计算机程序都是面向过程和面向对象的结合使用,面向对象同样也支持面向过程
1.1.1 面向对象技术简介
类(Class)
: 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。类变量
:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。数据成员
:类变量或者实例变量用于处理类及其实例对象的相关的数据。方法重写
:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。实例变量
:定义在方法中的变量,只作用于当前实例的类。继承
:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。实例化
:创建一个类的实例,类的具体对象。方法
:类中定义的函数。对象
:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
1.2 类和对象:
1.2.1 类定义:
class ClassName:
<statement-1>
.
.
<statement-N>
1.2.2 类的使用–实例化类的对象:
#!/usr/bin/python3
# 类的定义
class MyClass:
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
# 结果:
# MyClass 类的属性 i 为: 12345
# MyClass 类的方法 f 输出为: hello world
1.3 类的组成–实例属性和方法:
- 类由三个部分组成
- 实例属性或者叫对象属性 或简称属性
- 方法–可理解为在面向过程中定义的函数, 但是首个参数必须是‘self’
- 类属性–没有前两个那么常用和重要
- 代码示例:
# 实例属性 必须通过初始化或者实例化对象,通过对象去访问,
class Student(object):
def __init__(self, name):
self.name = name
s = Student('Bob')
print(s.name )
# 类属性 不需要实例化对象,直接通过类名访问
class Student(object):
name = 'Student'
print(Student.name)
# 面向对象
# 属性和方法
class Student(object):
# 初始化方法 self指向创建的实例本身
def __init__(self,name,score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name,self.score))
# 实例化对象1
xiaohong = Student('xiaohong',98)
print(id(xiaohong))
# 实例化对象2
xiaobai = Student('xiaobai',81)
print(id(xiaobai))
# 实例化对象3
xiaobai = Student('xiaobai',81)
print(id(xiaobai))
1.4 构造方法–对象方法中的特殊方法:
- 很多类都倾向于将对象创建为有初始状态的。因此类可能会定义一个名为 init() 的特殊方法(构造方法),像下面这样:
def __init__(self):
self.data = []
- 类定义了 init() 方法的话,类的实例化操作会自动调用 init() 方法。所以在下例中,可以这样创建一个新的实例:
x = MyClass()
- 当然, init() 方法可以有参数,参数通过 init() 传递到类的实例化操作上。例如:
#!/usr/bin/python3
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
1.4.1 self关键字–代表类的实例,而非类
- 方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
- 以上实例执行结果为:
<__main__.Test instance at 0x100771878>
__main__.Test
- 从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。
- self 不是 python 关键字,我们可以换成其他变量名
1.5 总结
1.5.1 面向对象编程概括
- 面向对象编程是一种程序设计思想
- 面向对象把类和对象作为程序的基本单元
- 对象包含属性和方法
- 面向过程编程为:函数的调用集合
- 面向对象编程为:对象之间传递信息的集合
- 处处皆对象
1.5.2 类和实例总结
-
类可以理解为图纸或者模版
-
实例是根据类的图纸或者模版创建出来的一个一个对象
-
类定义class,关键字self
-
类的初始化函数__init__
-
面向对象三大特点:继承,封装,多态
-
属性和方法
1.6 访问限制
- 通过”__”两个下划线可以修饰私有变量
- 通过编写get和set方法来修改对象的属性
- Python中没有真正的私有属性和私有方法
class Student(object):
# 方法 self指向创建的实例本身
def __init__(self,name,score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name,self.__score))
def get_grade(self):
if self.__score >= 90:
return 'A'
elif self.__score >= 60:
return 'B'
else:
return 'C'
def set_score(self,score):
if 0<=score<=100:
self.__score=score
else:
raise ValueError('分数请大于0小于等于100')
def get_score(self):
return self.__score
xiaolv = Student('xiaolv',45)
print(xiaolv.set_score(98))
print(xiaolv.get_score())
# python没有真正的是私有,把私有改名称_Student__name
print(xiaolv._Student__name)
2 面向对象—继承和多态
2.1 继承
- 定义一个class的时候,可以从某个现有的class继承,新的 class称为子类(Subclass)
- 被继承的class称为基类、父类或超类(Base class、Super class)
class Animal(object):
def run(self):
print('Animal is running')
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
# dog.run()
cat = Cat()
# cat.run()
2.1.1 多继承【扩展】
-
Python同样有限的支持多继承形式。
-
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
#类定义
class People:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class Student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class Speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class Sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = Sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中排前地父类的方法
# 执行以上程序输出结果为:
# 我叫 Tim,我是一个演说家,我演讲的主题是 Python
2.2.2 方法重写
- 如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法
class Animal(object):
def run(self):
print('Animal is running')
class Dog(Animal):
def run(self): # 重写
# 调用父类的run方法
# super().run()
print('Dog is running')
def eat(self):
print('eat meat')
dog = Dog()
dog.run()
class Cat(Animal):
def run(self): # 重写
# 调用父类的run方法
# super().run()
print('Cat is running')
def eat(self):
print('eat fish')
2.3 多态
- 代码运行时才确定对象的具体类型
b=Animal() # b是Animal类型
c=Dog() # c是Dog类型
print(isinstance(b, Animal))
print(isinstance(c, Dog))
print