1 概述
Python支持面向过程 | 面向对象 | 函数式编程等多种范式
面向对象编程是将数据和操作数据的方法封装到对象中
面向对象关注的是软件中对象之间的关系,适合大型程序
面向对象是宏观分解,底层仍是面向过程
面向对象,设计者思维;面向过程,执行者思维
软件行业,一个好的设计者必然也是一个好的执行者
解决问题: 面向对象思维统一中国
1.中国分为各阶级
2.解决各阶级间的关系
2 对象的进化
数据 -> 变多 -> 数组
数据 -> 类型变复杂 -> 结构体
struct resume{
int age;
char name[10];
double salary;
};
数据 -> 逻辑变复杂 -> 对象
对象封装处理数据的方法
3 类定义 | 对象创建
类是制造对象的模具
类也是对象
对象的方法由同一类的所有对象共享
# 首字母大写,驼峰
class Student:
# 构造函数,self必须位于第一个参数,存对象引用地址
def __init__(self,name,score):
self.name = name
self.score = score
def say_score(self):
print('{0}的分数是{1}'.format(self.name,self.score))
s1 = Student('Vincent',99)
s1.say_score()
4 构造函数 - init
对象的value即属性和方法
普通方法第一个参数也是self
self相当于c++中的self指针,java\c#中的this
5 实例属性
从属于实例对象的属性
class Student:
def __init__(self,name,age):
...
s1.age = 32
s1.salary = 3000
print(s1.age)
6 实例方法
从属于实例对象的方法
s2 = Student('Chris',100)
s2.say_score()
# 解释器执行实质,方法在类中,方法是共享的
Student.say_score(s2)
其他方法:
dir(obj)
获得对象的所有属性和方法
obj.dict
获得对象的属性字典
pass
空语句
isinstance(obj,Student)
判断对象是否是类的实例
7 类对象
class Student:
pass
print(type(Student))
print(id(Student))
Stu2 = Student
s1 = Stu2()
print(s1)
8 类属性
从属于类对象,可以被所有对象共享
class Student:
company = 'DFUN'
count = 0
def __init__(self, name, score):
self.name = name
self.score = score
Student.count = Student.count + 1
def say_score(self):
print('公司{0},姓名{1},分数{2}'.format(Student.company, self.name, self.score))
s1 = Student('Vincent', 100)
s1.say_score()
s2 = Student('Chris', 99)
print(Student.count)
print(s1.count)
9 类方法 | 静态方法
类方法
从属于类对象的方法
# 类方法通过装饰器@classmethod定义
class Student:
company = 'DFUN'
@classmethod
# 第一个参数cls必须有,代表类对象
def printCompany(cls):
print(cls.company)
Student.printCompany()
静态方法
与类对象无关的方法,不操作类属性
class Student:
company = 'DFUN'
@staticmethod
def add(a,b):
print(a+b)
Student.add(1,2)
说明:
类方法和静态方法中不能调用实例变量,实例方法
10 析构方法
释放对象占用的资源,如打开的文件\网络连接等
python自动垃圾回收机制(引用计数)调用del方法回收对象
class Person:
def __del__(self):
print('销毁对象')
p1 = Person()
p2 = Person()
del p2
print('程序结束')
# 打印程序结束后会调用p1的析构方法
11 call方法
定义了__call __方法的对象,则对象可以像函数一样调用,实际调用的是call方法
本质上a+b解释器执行的是对象的add方法
class SalaryCal:
'''工资计算类'''
def __call__(self,salary):
print('计算工资...')
yearSalary = salary*12
daySalary = salary/22.5
hourSalary = daySalary//8
return dict(yearSalary=yearSalary,daySalary=daySalary,hourSalary=hourSalary)
s = SalaryCount()
print(s(3000))
12 方法无重载 | 方法动态性
方法无重载
python中方法没有重载,是由于python中参数没有类型
参数数量也可以由可变参数控制
class Person:
def say_hi(self):
print('hello')
# 只有第二个有效,第一个被覆盖
def say_hi(self,name):
print('hello,{0}'.format(name))
方法动态性
class Person:
def work(self):
print('努力工作')
def play(s):
print('{0}在玩游戏'.format(s))
def work2(s):
print('努力上班')
Person.play = play
p = Person()
p.work()
p.play('Vincent')
# 覆盖原有方法
Person.work = work2
p.work()
python中方法没有重载,是由于python中参数没有类型
参数数量也可以由可变参数控制
class Person:
def say_hi(self):
print('hello')
# 只有第二个有效,第一个被覆盖
def say_hi(self,name):
print('hello,{0}'.format(name))
方法的动态性
class Person:
def work(self):
print('努力工作')
def play(s):
print('{0}在玩游戏'.format(s))
def work2(s):
print('努力上班')
Person.play = play
p = Person()
p.work()
p.play('Vincent')
# 覆盖原有方法
Person.work = work2
p.work()
13 私有属性
python对于类的成员没有严格的访问控制限制
1.通常约定,开头属性是私有的,其他为公共的
2.类内部可以访问私有属性\方法
3.类外部不能直接访问私有属性\方法
4.类名_私有属性\方法名,外部访问
# 测试私有属性
class Employee:
def __init__(self,name,age):
self.name = name
self.__age = age
e = Employee('Vincent',18)
print(e.name)
# 私有属性外部不能直接访问,报错
# print(e.age)
print(e._Employee__age)
14 私有方法
class Employee:
# 类变量也可以私有
__company = 'DFUN'
...
def __work():
print('努力工作')
# 类内部可以调用私有属性
print(self.__age)
e = Employee('Vincent',18)
# 私有方法外部调用
e._Employee_work()
# 类外部调用私有类变量
print(Employee._Employee__company)
15 装饰器 | get set方法
@property
将一个方法调用变为属性调用
class Employee:
@property
def salary(self):
print('salary')
emp = Employee()
print(emp.salary)
私有属性封装get\set方法
class Employee:
def __init__(self,name,salary):
# 私有属性
self.__name = name
self.__salary = salary
def get_salary(self):
return self.__salary
def set_salary(self,salary):
# 增加判断逻辑
if 1000<salary<50000:
self.__salary = salary
else:
print('录入错误')
emp = Employee('Vincent',18)
emp.set_salary(2000)
print(emp.get_salary())
使用@property封装get\set方法
class Employee:
def __init__(self,name,salary):
# 私有属性
self.__name = name
self.__salary = salary
@property
def salary(self):
return self.__salary
@salary.setter
def set_salary(self,salary):
# 增加判断逻辑
if 1000<salary<50000:
self.__salary = salary
else:
print('录入错误')
emp = Employee('Vincent',18)
emp.salary = 2000
print(emp.salary)
16 面向对象三大特性
封装 | 继承 | 多态
封装
隐藏细节如私有属性,只对外提供必要的方法
python没有严格的访问控制符语法,靠程序员自觉实现
继承
让子类具有父类特性,提高代码重用性
从设计上是一种增量进化
多态
同一方法调用由于调用对象不同产生不同的行为
17 继承
python支持多重继承
若没有指定父类,则默认父类是object
class Person:
def __init__(self,name,age):
self.name = name
# 私有属性
self.__age = age
def say_age(self):
print('年龄{}'.format(self.age))
class Student(Person):
def __init__(self,name,age,score):
# 调用父类构造方法,必须显示调用父类的构造方法
Person.__init__(self,name,age)
self.score = score
print(Student.mro())
s = Student()
# 子类调用父类方法
s.say_age()
print(s.name)
# 报错,父类私有属性可以被继承但不能直接用
# print(s.age)
print(s._Person__age)
18 方法重写
子类重新定义父类方法,将其覆盖
class Person:
def __init__(self,name,age):
self.name = name
# 私有属性
self.__age = age
def say_age(self):
print('年龄{}'.format(self.age))
def say_introduce(self):
print('我的名字是{}'.format(self.name))
class Student(Person):
def __init__(self,name,age,score):
# 调用父类构造方法,必须显示调用父类的构造方法
Person.__init__(self,name,age)
self.score = score
# 重写父类方法
def say_introduce(self):
print('报告老师,我的名字是{}'.format(self.name))
s = Student('Vincent',18,100)
s.say_introduce()
19 根类 - object
mro()
查看类的继承层次结构
object根类
obj = object()
# 查看对象属性
print(dir(obj))
20 重写str方法
class Person:
def __init__(self,name,age):
self.name = name
def __str__(self):
return '名字是{}'.format(self.name)
p = Person('Vincent')
print(p)
21 多重继承
python支持多重继承,但会使类层次结构变复杂,尽量避免使用
class A:
def aa(self):
print('aa')
class B:
def bb(self):
print('bb')
class C(A,B):
def cc(self):
print('cc')
c = C()
c.aa()
c.bb()
c.cc()
22 多继承父类方法重名 - mro
当多继承时,不同父类具有同名方法,按照从左到右的顺序执行
23 获取父类定义 - super
class A:
def say(self):
print('A',self)
class B(A):
def say(self):
# A.say()
super.say()
print('B',self)
B().say
23 多态
多态
同一方法调用由于对象不同产生不同行为
两个必要条件:继承\方法重写
class Man:
def eat(self):
print('吃饭')
class Chinese(Man):
def eat(self):
print('中国人吃饭')
class English(Man):
def eat(self):
print('英国人吃饭')
def manEat(m):
if isinstance(m,Man):
m.eat()
else:
print('不能吃饭')
manEat(Chinese())
manEat(English())
25 运算符重载
python运算符实质是调用对象的特殊方法实现
每个运算符实质都对应了相应的方法
字符串乘法实际是调用了_mul_
a = 10
b = 20
c = a.__add__(b)
常见特殊方法
_init_
_del_
等
测试-重写add方法
class Person:
def __init__(self,name):
self.name = name
# 同理可定义__mul__乘法运算
def __add__(self,other):
if isinstance(other,Person):
return '{}--{}'.format(self.name,other.name)
else:
return '不是同类对象'
p1 = Person('Vincent')
p2 = Person('Chris')
x = p1 + p2
print(x)
26 特殊属性
_class_ 对象所属类
_bases_ 基类元组
_base_ 基类
class A:
def a(self):
print('aa')
a = A()
print(a.__dict__)
print(a.__class__)
# 父类列表
print(A.__bases__)
# 类的继承结构
print(a.mro())
# 子类列表
print(A.__subclasses__)
27 对象浅拷贝 | 深拷贝
根据是否拷贝对象的子对象区分深浅
python拷贝一般都是浅拷贝
深拷贝通过copy的deepcopy函数实现
import copy
# 测试对象的深浅拷贝
class MobilePhone:
def __init__(self,cpu,screen):
self.cpu = cpu
self.screen = screen
class CPU:
def cal(self):
print('计算')
class Screen:
def show(self):
print('显示')
c1 = CPU()
# c2\c1指向同一对象
c2 = c1
print(c1)
print(c2)
s1 = Screen()
# 测试浅复制
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)
# 浅复制子对象相同
print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m2.screen)
# 测试深复制
m3 = copy.deepcopy(m1)
# 深复制子对象不同
print(m3,m2.cpu,m2.screen)
28 组合
is-a 继承
has-a 组合,如手机有CPU
class A1:
def say(self):
print('a1')
class B1(A1):
b1 = B1()
# 继承方式实现代码复用
b1.say()
class A2:
def say(self):
print('a2')
class B2:
def __init__(self,a)
self.a = a
a2 = A2()
b2 = B2(a2)
# 组合方式实现代码复用
b2.a.say()
29 设计模式-工厂模式
实现调用者与实现者的分离
设计模式实质就是分离
规模越大的软件越需要设计模式
class CarFactory:
def createCar(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
fac = CarFactory()
c1 = fac.createCar('奔驰')
c2 = fac.createCar('比亚迪')
print(c1)
print(c2)
30 设计模式-单例模式
单例模式
确保一个类只有一个实例,提供一个访问该实例的全局访问点
降低开销
# 测试单例模式
class MySingleton:
__obj = None
__init_flag = True
def __new__(cls,*args,**kargs):
if cls.__obj == None:
cls.__ojb = object.__new__(cls)
return cls.__obj
def __init__(self,name):
# 保证初始化方法只被调用一次
if MySingleton.__init_flag:
print('init...')
self.name = name
MySingleton.__init_flag = False
a = MySingleton('aa')
b = MySingleton('bb')
# a\b为同一对象
print(a)
print(b)
练习: 整合工厂 | 单例









网友评论