python面向对象
基础概念:
class Dog: d_type = "金毛" # 类属性,所有实例共享 # 解释器执行实例化代码,会先在内存中创建该类实例对象,然后调用类 的__init__方法。 # 调用 __init__方法时,就将实例对象 传递给 self参数,self 参数变量 指向的 就是 实例对象 本身 def __init__(self, name, age): # 初始化方法/实例方法,实例化时会自动执行,创建一些实例属性 self.name = name # 实例属性,每个实例独享 self.age = age # 实例属性通常在类的初始化方法里面定义
@classmethod # 类方法只能访问类属性,不能访问实例属性
def class_method(cls): # 不操作任何实例的话就应该定义为类方法
print('class method called',cls)
@staticmethod
def haha(): # 静态方法不能访问实例属性也不能访问类属性,没有传入self
print('hello world!')
def say_hi(self): # 类的实例方法,都是要访问类的实例属性的 或 操作实例属性 print("hello, I am a dog,my type is ",self.d_type,self)
dog = Dog('小金',2)
# 通过类名访问类属性
print(Dog.d_type)
# 通过实例名访问类属性
print(d.d_type)
# 不能通过类名访问实例属性
print(Dog.name)
# 实例给类属性赋值,相当于给实例创建了一个新的实例属性
dog.d_type = '二哈'
print(dog.d_type)
print(Dog.d_type)
-------------------------------------------------------------------------
类与类(接口)之间的关系:实现关系、依赖关系、关联关系、聚合关系、组合关系、继承关系。
举例说明几种关系:
- 依赖关系:狗和主人的关系
- 关联关系:你和你女朋友的关系
- 聚合关系:电脑的各部件组成完整的电脑,电脑里面有CPU,硬盘,内存等。每个组件都有自己的生命周期,电脑挂了,CPU还是好的,还是完整的个体
- 组合关系:比聚合还要紧密,比如人的大脑,心脏,各个器官。这些器官组成一个人,如果人挂了,其他东西也跟着挂了
实现关系(Realization):是一种类与接口的关系,指一个类实现一个或多个接口功能的过程,这里的接口更多的是一种契约或规范。实现是两个类之间或类与接口之间耦合度最大的关系之一,在这种关系中,类实现了接口或接口类中所声明的操作
代码实现的二种形式:
- 类具体实现接口中所声明的操作:如Java中支持原生interface,可以直接implement
- 类具体实现接口类中所声明的操作:如python中无原生interface,这里的接口类更多的是逻辑上的契约或规范
UML中使用带三角箭头的虚线,箭头指向接口

代码实现:
class Car(object): # 待实现的接口 def engine(self): raise NotImplementedError class Benz(Car): # 具体实现所定义的引擎 def engine(self): print ("奔驰嘟嘟~~~") class BMW(Car): def engine(self): print ("宝马嘟嘟~~~")
benz = Benz() bmw = BMW() benz.engine()
bmw.engine()
依赖关系(Dependency):是一种使用的关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依赖.
代码表现:局部变量、方法的参数或者对静态方法的调用
三种形式:
- 类B作为类A方法的形参
- 类B作为类A方法的局部变量
- 类A调用类B的静态方法
UML中使用带箭头的虚线表示,箭头指向表示调用关系,从类A指向类B

代码实现:
类B作为类A方法的形参
class Person(object): # 类A def flying(self, plane): plane.fly() # 在类A中调用类B的方法 class Plane(object): # 类B作为一个参数传递给类A def fly(self): print ("飞机起飞了。。。") person = Person() plane = Plane() person.flying(plane) # 传入类B
类B作为类A方法的局部变量
class Person(object): # 类A def flying(self): self.plane = Plane() # 类B作为类A实例属性 plane.fly() # 调用类B的方法 class Plane(object): # 类B def fly(self): print ("飞机起飞了。。。") person = Person() person.flying()
类A调用类B的静态方法
class Person(object): # 类A def flying(self): Plane.fly() # 直接调用类B的静态方法 class Plane(object): # 类B @staticmethod # 类B的静态方法 def fly(): print ("飞机起飞了。。。") person = Person() person.flying()
关联关系(Association):是一种长期性的、拥有的关系,它使一个类知道另一个类的属性和方法,双方的关系一般是平等的,如学校与学生之间、老师与学生之间。被关联类B以类的属性形式出现在关联类A中,双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。
依赖关系与关联关系的区别有动静之分,依赖关系的偶然性和临时性说明了动态性,关联关系的长期性、拥有性静态地展示了对被关联类的引用。
四种形式:
- 单向关联:单向拥有关系,只有一个类知道另一个类的属性和方法
- 双向关联:双向拥有关系,双方都知道对方的属性和方法
- 自身关联:自己关联自己,这种情况比较少但也有用到,如链表
- 多重性关联:表示两个类的对象在数量上的对应关系,多重性可在关联线上用数字范围表示

UML中使用直线箭头表示,箭头指向为被关联的类,从类A指向类B
单向关联

双向关联

自我关联

多重性关联

代码实现:
单向关联
class Student(object): # 类B def __init__(self): self.title = "张三" def study(self): print ("学习中...") class School(object): # 类A 知道类B的属性和方法 def __init__(self): self.address = "北厂街" self.student = Student() # 实例化类B def act(self): print(self.student.title) # 打印类B的实例属性title self.student.study() # 调用类B的实例方法 study school = School() school.act()
双向关联
class Student(object): # 类B def __init__(self): self.school = School() # 实例化类A class School(object): # 类A def __init__(self): self.student = Student() # 实例化类B
自我关联
class Node(object): def __init__(self): self.next = Node() #调用自己 class ListNode: """链表节点类""" def __init__(self, val: int): self.val: int = val # 节点值 self.next = None # 指向下一节点的指针(引用)
聚合关系(Aggregation):聚合关系是关联关系的特例,是整体和部分的关系,聚合关系中的整体和部分是可以分离的,生命周期也是相互独立的,如计算机与CPU、公司与员工的关系、车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。
uml中使用 带空心菱形的实心线,空心菱形指向整体(类A),实线箭头边指向部分(类B)

代码实现:
类A由类B聚合而成,类A包含有类B的全局对象,但类B的对象可以不在类A创建的时刻创建
class School(object): # 类A def __init__(self): self.__students = [] # 类B的对象不在类A初始化时创建 def add_student(self, student): self.__students.append(student) class Student(object): # 类B pass student = Student() school = School() school.add_student(student)
组合关系(Composition):组合关系也是关联关系的特例,属于强聚合,本身也表示整体与部分的关系,但部分不能离开整体而单独存在,整体生命周期的结束时也是部分的生命周期到头时。如人和大脑,如公司和部门是整体和部分的关系,没有公司就不存在部门。
聚合和组合其实都是关联的特例,都是整体与部分的关系。它们的区别在于整体和部分是否可分离,
聚合的两个对象之间是可分离的,且具有各自的生命周期
而组合的两个对象往往表现为一种同命相连的关系。
uml中使用带实心菱形的实线,菱形指向整体

代码实现
class Company(object): def __init__(self): print("公司有多个部门:") self.__partmentA = PartmentA()
self.__partmentB = PartmentB()def run(self): print("打卡上班...") class PartmentA(object): def __init__(self): print("公司的部门A")
class PartmentB(object):
def __init__(self):
print("公司的部门B")
company = Company()
company.run()
继承关系(泛化关系 Generalization):是一种继承关系,它指定了子类如何特化父类的所有特征和行为,即子类继承父类、或子接口继承父接口的功能并增加自己新功能的过程。例如:老虎是动物的一种,即有老虎的特性也有动物的共性
父类称为基类或超类,子类也称为派生类。子类可以继承自抽象类或普通类。
二种形式:
- 子类继承自抽象类或普通类
- 子接口继承自父接口:适用于Java
UML中使用带三角箭头的实线,箭头由子类指向父类、或子接口指向父接口

代码实现:
子类继承自抽象类,必须实现父类中@abstractmethod修饰的抽象方法
from abc import ABCMeta, abstractmethod
# 抽象基类是一种不能直接被实例化的类,它的主要作用是定义接口和规范子类的行为
class Animal(metaclass=ABCMeta): # 父类
def __init__(self): self.name = "动物"
# ABC 是一个抽象基类,它的子类必须实现指定的抽象方法 @abstractmethod # abstractmethod是一个装饰器,用于指定一个抽象方法 def run(self): print ("奔跑的动物。。。") def play(self): print ("动物在玩耍。。。") class Dog(Animal): def __init__(self): self.name = "狗子 def run(self): print ("奔跑的狗子。。。") def __bark(self): print ("狗子汪汪汪。。。") class Cat(Animal): def __init__(self): self.name = "喵咪" def run(self): print ("奔跑的动物。。。") def play(self): print ("喵咪在玩耍。。。") def __jump(self): print ("喵咪蹦蹦跳。。。") dog = Dog() cat = Cat() dog.run() dog.play() cat.run() cat.play()
子类继承自普通类,子类方法重写父类同名非私有方法
class Animal(object): def __init__(self): self.name = "动物" def run(self): print ("奔跑的动物。。。") def play(self): print ("动物在玩耍。。。") class Dog(Animal): def __init__(self): self.name = "狗子" def run(self): print ("奔跑的狗子。。。") def __bark(self): print ("狗子汪汪汪。。。") class Cat(Animal): def __init__(self): self.name = "喵咪" def play(self): print ("奔跑的喵咪。。。") def __jump(self): print ("喵咪蹦蹦跳。。。") dog = Dog() cat = Cat() dog.run() dog.play() cat.run() cat.play()
关系的强弱:继承 = 实现 > 组合 > 聚合 > 关联 > 依赖
关联和依赖的区别:
- 关联关系强、长期
- 关联关系是通过属性来实现;依赖关联是通过方法形参或者局部变量实现
关联、组合/聚合的异同
- 相同:都是关联,都是做类的属性
- 不同点:组合 /聚合表示的是整体和部分的关系,关联可以表示所有关系
组合和聚合的异同
- 相同:都是关联的特例,都是表示的整体和部分的关系
- 不同点:整体部分的生命周期是否相同?组合更强
参考学习:https://www.cnblogs.com/coolstream/p/9499299.html
--------------------------------------------------------------------------
面向对象三大特性:
- 封装
- 继承
- 多态
三大特性之-封装:
封装相当于一个保护屏障,防止这个类的代码和数据被外部代码随机访问。
原则:
1,将不需要对外提供的内容隐藏
2,隐藏属性,提供公共方法对其访问
私有变量和私有方法:在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
class Person(object): def __init__(self, name, age): self.name = name # 实例变量,成员变量 self.age = age self.__life_val = 100 # 私有变量,私有属性 def get_life_val(self): print("生命值 还有",self.__life_val) return self.__life_val def __breath(self): # 私有函数 print("%s is breathing..." % self.name) def got_attack(self): # 封装 self.__life_val -= 20 print("被攻击了,生命值减20") self.__breath() return self.__life_val
a = Person('张三',20) # 实例化一个类
a.get_life_val() # 通过公共方法访问 私有变量
a.got_attack() # 通过公共方法访问 私有函数
# 访问私有函数:实例名._类名+方法名()
a._Person__breath()
# 修改私有属性
a._Person__life_val = 11
# 查看修改后的生命值
a.get_life_val()
# 实例生成后,再创建的私有属性,并不具有私有性,可以直接访问
a.__val = 333
print(a.__val) # 直接访问属性
三大特性之-继承:见类的关系之继承关系。
在python中,有两种类的写法,不用写法采用的继承顺序不同
class A: # 经典类
pass
class B(object): # 新式类
pass
在python2中,经典类采用的是深度优先查找法,新式类采用的是广度优先
在python3中,无论是经典类,还是新式类,都是按广度优先查找
Python2.x中默认都是经典类,只有显示继承了object的才是新式类
Python3.x中默认都是新式类,不必显式的继承object.
之所以在python3中全部改成了广度优先,是因为深度优先在某些特殊情况下,会出现BUG。
多继承之C3算法

# class A: def test(self): print("from A") class B(A): # def test(self): # print('from B') pass class B2: def test(self): print('from B2') class C(A): def test(self): print('from C') class C2: def test(self): print('from C2') class D(B,B2): # def test(self): # print('from D') pass class E(C,C2): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1 = F() f1.test() print(F.__mro__) # 打印类的继承顺序
三大特性之-多态:
有时候一个对象会有多种表现形式,比如网站页面有个button按钮,这个button的设计可以不一样(单选框、多选框、圆角的点击按钮、直角的点击按钮等),尽管长的不一样,但它们都有一个共同的调用方式,就是onClick()方法。我们只要在页面上一点击就会触发这个方法。点完后有的按钮会变成选中状态、有的会提交表单、有的甚至会弹窗。
这种多个对象共用一个接口,又表现的形态不一样的现象,就叫做多态。
1,通过统一函数接口实现多态
2,通过抽象类实现多态(常用)
# 通过统一函数接口实现多态 class Dog(object): def sound(self): print('汪汪汪。。。') class Cat(object): def sound(self): print('喵喵喵。。。') def make_sound(animal_type): """统一调用接口""" animal_type.sound() # 不管传进来什么动物,我都调用sound()方法 dogObj = Dog() catObj = Cat() make_sound(dogObj) make_sound(catObj)
# 通过抽象类实现多态(常用) class Document: # 文件 def __init__(self, name): self.name = name def show(self): raise NotImplementedError("Subclass must implement abstract method.") class Pdf(Document): # 继承Document,文件类型为PDF def show(self): return 'Show pdf contents!' class Word(Document): # 文件类型为word def show(self): return 'Show word contents' pdf_obj = Pdf("练习题目.pdf") print(pdf_obj.show())

浙公网安备 33010602011771号