文章目录
一. 面对对象三大特征介绍
- 封装(隐藏)
通过私有属性,私有方法的方式进行封装
- 继承
继承可以让子类继承父类特性,提高代码重用性
是一种增量进化,在父类基础上增加功能,改进算法
- 多态
同一种方法调用对象不同会产生不同行为
1. 继承
- 已有的类称为父类或基类,新的类称为子类或派生类
- Python支持多重继承,一个子类可以继承多个父类
- 类定义中若没有指定父类,则默认是object类,它是所有类的父类,里面定义了一些类共有的默认操作,比如__new__
- 定义子类时,必须在其构造函数内调用父类的构造函数
#测试继承的基本使用
class Person: #可以不定义构造器
def say_age(self):
print("年龄我不知道")
class Student(Person):
pass
print(Student.mro()) #查看继承结构
s=Student()
s.say_age()
# 测试继承的基本使用
class Person:
def __init__(self,name,age):
self.name=name
self.__age=age #父类的私有属性,子类也会继承,但是要带上父类名去调用
def say_age(self):
print("年龄我不知道")
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age) #子类必须显示调用父类构造器,共享父类代码
self.score=score #自己特有的属性
print(Student.mro()) # 查看继承结构
s = Student("gao",18,72)
s.say_age()
print(s.name)
#print(s.age) #'Student' object has no attribute 'age'
print(s.__dict__) #{'name': 'gao', '_Person__age': 18, 'score': 72}说明继承了,不过名字里有父类
print(s._Person__age)
1. 类成员的继承与重写
- 子类继承了父类除构造方法之外的所有成员(包括私有属性和方法,但要通过父类名来调用)
- 方法重写:子类可以重新定义父类中的方法,这样会覆盖父类的方法
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age # 父类的私有属性,子类也会继承,但是要带上父类名去调用
def say_age(self):
print("我的年龄是:",self.age)
def say_name(self):
print("我的名字是:{0}".format(self.name))
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age) # 子类必须显示调用父类构造器,共享父类代码
self.score = score # 自己特有的属性
def say_name(self):
print("报告老师,我的名字是:",self.name)
s = Student("gao", 18, 72)
s.say_name()
2. 常用方法
3. 多重继承
- 多重继承使类的整体层次异常复杂,尽量避免使用
- 父类出现相同名字方法,从左至右搜索
- mro也是按从左至右的顺序
class A:
def aa(self):
print("aa")
def say(self):
print("AAA")
class B:
def bb(self):
print("bb")
def say(self):
print("BBB")
class C(B,A): #没有构造函数,也可以继承
def __init__(self,name):
self.name=name
def cc(self):
print("cc")
c=C(3)
print(C.mro()) #[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
c.aa()
c.bb()
c.cc()
c.say() #父类中出现名称相同的方法,按从左向右搜索
4. super()获得父类定义
- 子类中想获得父类方法,可以通过super()
- 和直接用父类名调用效果一样
class A:
def say(self):
print("A:",self)
print("say AAA")
class B(A):
def say(self):
super().say() #和直接用A.say()效果一样
print("B:",self)
b=B()
b.say()
2. 多态
- 多态指同一方法调用由于对象不同会产生不同行为
- 方法有多态,属性没有多态
- 多态必要条件:继承,方法重写
class Man:
def eat(self):
print("饿了,吃饭")
class Chinese(Man):
def eat(self):
print("用筷子吃饭")
class English(Man):
def eat(self):
print("用叉子吃饭")
class Indian(Man):
def eat(self):
print("用右手吃饭")
def manEat(m):
if isinstance(m,Man):
m.eat()
else:
print("不能吃饭")
#Chinese.eat() #TypeError: eat() missing 1 required positional argument: 'self'
manEat(Chinese)
manEat(English()) #有没有括号都可以
二. 特殊方法和属性
1. 特殊方法和运算符重载
- Python的运算符实际上是通过调用对象的特殊方法实现的
- 常见的特殊方法:
__init __: 构造方法 (对象创建:p=Person())
__del __:析构方法
__call __:函数调用(函数名(参数)直接调用被__call __定义过的方法)
__len __:长度
- 每个运算符都对应了相应方法:
+:__add __
-:__sub __
<,<=,==,>,>=,!=:__lt __, __le __, __eq __, __gt __, __ge __, __ne __
|,^,&:__or __, __xor __, __and __
<<,>>:__lshift __, __rshift __
*,/,%,//:__mul __, __truediv __, __mod __, __floordiv __
** : __pow __
- 可以重写上述特殊方法,实现运算符重载
class Person:
def __init__(self,name):
self.name=name
def __add__(self,other):
if isinstance(other,Person):
return("{0}--{1}".format(self.name,other.name)) #注意是other.name
else:
return "不是同类"
def __mul__(self,other):
if isinstance(other,int):
return self.name*other
else:
return"不是同类对象"
p1=Person("gao")
p2=Person("peng")
x=p1+p2 #加号调用的是__add__函数
print(x)
print(p1*3) #乘号调用的是__mul__函数
2. 特殊属性
class A:
def aa(self):
print("aa")
def say(self):
print("AAA")
class B:
def bb(self):
print("bb")
def say(self):
print("BBB")
class C(B,A): #没有构造函数,也可以继承
def __init__(self,name):
self.name=name
def cc(self):
print("cc")
c=C(3)
c.aa()
c.bb()
c.cc()
c.say() #父类中出现名称相同的方法,按从左向右搜索
print(dir(c)) #dir()是内置函数
print(c.__dict__)
print(c.__class__)
print(C.__bases__) #只有一个父类用base,必须用C(类型名),而不是c
print(C.mro()) #必须用C(类型名),而不是c
print(A.__subclasses__) #用类型名
三. 浅拷贝与深拷贝
- 变量的赋值:只是形成两个变量指向同一对象
- 浅拷贝:对象包含的子对象内容不拷贝,源对象与拷贝对象引用同一子对象
- 递归拷贝对象中包含的子对象,源对象与拷贝对象的子对象不同
#测试对象的浅拷贝,深拷贝
import copy #copy要导入copy包
class MobilePhone:
def __init__(self,CPU,screen):
self.CPU=CPU
self.screen=screen
class CPU:
def calculate(self):
print("算1234567")
print("cpu对象:",self)
class Screen:
def show(self):
print("显示一个好看的画面")
print("screen对象:",self)
#测试变量赋值
c1=CPU()
c2=c1
print(c2)
print(c1)
'''地址相同
<__main__.CPU object at 0x000001870105EC48>
<__main__.CPU object at 0x000001870105EC48>
'''
#测试浅复制
s1=Screen()
m1=MobilePhone(c1,s1)
m2=copy.copy(m1)
print(m1,m1.CPU,m1.screen)
print(m2,m2.CPU,m2.screen)
'''
m1和m2不同,cpu和screen相同
<__main__.MobilePhone object at 0x0000018701066088> <__main__.CPU object at 0x000001870105EC48> <__main__.Screen object at 0x000001870105EB88>
<__main__.MobilePhone object at 0x0000018701066108> <__main__.CPU object at 0x000001870105EC48> <__main__.Screen object at 0x000001870105EB88>
'''
#测试深复制
m3=copy.deepcopy(m1)
print(m1,m1.CPU,m1.screen)
print(m3,m3.CPU,m3.screen)
'''
都不相同
<__main__.MobilePhone object at 0x0000018701066088> <__main__.CPU object at 0x000001870105EC48> <__main__.Screen object at 0x000001870105EB88>
<__main__.MobilePhone object at 0x0000018700FE97C8> <__main__.CPU object at 0x0000018700FEB048> <__main__.Screen object at 0x0000018701066148>
'''
四. 组合
is关系用继承,has关系用组合
#测试组合
#继承:
class A1:
def say_a1(self):
print("a1,a1,a1")
class A2(A1):
pass
a2=A2()
a2.say_a1()
#组合:
class A1():
def say_a1(self):
print("a1,a1,a1")
class A2:
def __init__(self,a):
self.a=a
a1=A1()
a2=A2(a1) #或直接写成a2=A2(A1())
a2.a.say_a1()
五. 练习
1. 工厂模式
class CarFactory:
def create_car(self,brand):
if brand=="奔驰":
return Benz()
elif brand=="宝马":
return BMW()
elif brand== "比亚迪":
return BYD()
else:
return "未知品牌,无法创建"
class Benz:
pass
class BMW:
pass
class BYD:
pass
factory=CarFactory()
c1=factory.create_car("奔驰")
c2=factory.create_car("宝马")
print(c1,c2)
2. 单例模式
class MySingleton:
__obj=None #类属性
def __new__(cls,*args,**kwargs):
if cls.__obj==None:
cls.__obj=object.__new__(cls) #调用object类的__new__方法创建对象
return cls.__obj
def __init__(self,name):
print("init...")
self.name=name
a=MySingleton("aa")
b=MySingleton("bb")
print(a)
print(b)
'''创建了一次,但是初始化两次'''
class MySingleton:
__obj=None #类属性
__init_flag=True
def __new__(cls,*args,**kwargs):
if cls.__obj==None:
cls.__obj=object.__new__(cls) #调用object类的__new__方法创建对象
return cls.__obj
def __init__(self,name):
if MySingleton.__init_flag:
print("init...")
self.name=name
MySingleton.__init_flag=False #不能写成self.__init_flag
a=MySingleton("aa")
b=MySingleton("bb")
print(a)
print(b)