面向对象
- 对象创建、属性、定义
- 封装
- 继承
- 多态
- 单例
走进对象的世界
类的基本操作
定义
"""
面向对象:
程序 现实中
对象 具体的事物
现实中的事物 转换成代码程序
万事万物皆对象
面向过程 会因为局部影响全局,几乎全部影响
优点:
复用,更加灵活(只需要修复出现问题的结点)
关注的 个体 + 关系
类 、对象 、 属性、方法
对象:手机
对象的集合:
共同的特征:颜色 品牌 大小 价格 动作:打电话 发短信 上网 打游戏
类别:
手机类 学生类
特征: 姓名 年龄 身高 特征 血型 婚否 ------------> 属性
动作:刷抖音 敲代码 看书...------------> 方法
多个对象-------->提取对象的共同特征和动作--------->封装到一个类
"""
"""
# 定义 首字母大写,驼峰命名法;默认继承Object
class
"""
class Phone:
pass
# 属性
brand = '苹果'
# 方法
# <class '__main__.Phone'>
print(Phone)
# 使用模型创建对象
yh = Phone() # <__main__.Phone object at 0x000001DEAED95A88>
print(yh)
print(yh.brand)
yh.brand = '华为'
print(yh.brand)
ff = Phone()
print(ff) # <__main__.Phone object at 0x000001DEAED95AC8>
print(yh.brand)
ff.brand = '小米'
print(ff.brand)
print("属性".center(20, '*'))
"""
对象:
对象名= 类名(): 在内存就是内存空间分配
属性:
类属性和对象属性
先找对象属性再找类属性;
如果再找到对象属性则不会再找类属性
"""
class Student:
pass
# 类属性
name = ''
age = 0
xiaowei = Student()
# 对象属性
xiaowei.name = '小伟' # 赋值操作
xiaowei.age = 18
print(xiaowei.name)
print(xiaowei.age)
# 再创建一个对象
yy = Student()
yy.age = 30
print(yy.name)
print(yy.age)
# 初始化类属性
Student.age = 18
Student.name = "中国"
print(yy.name)
属性
"""
私有化装饰器:
先get后set:
@property
@age.setter
"""
class Student:
def __init__(self, name, age):
self.__name = name
self.__age = age
self.__score = 50
def __str__(self):
return "姓名是:" + self.__name + ",年龄:" + str(self.__age) + ",分数:" + str(self.__score)
# 先定义get_age
@property
def age(self):
return self.__age
# 再定义set_age;依赖于get
@age.setter
def age(self, age):
if age < 0 or age > 120:
print("年龄没有在合理范围内")
else:
self.__age = age
"""
# 定义公有的get和set方法
def set_age(self, age):
if age < 0 or age > 120:
print("年龄没有在合理范围内")
else:
self.__age = age
def get_age(self):
return self.__age
def set_score(self, score):
self.__score = score
def set_name(self, name):
if len(name) > 6:
print("名字长度不能超过六位")
else:
self.__name = name
def get_name(self):
return self.__name
"""
s = Student("lily", 30)
s.age = 131
result = s.age # 因为加了装饰器,可以像使用name一样
print(result)
print(dir(s))
方法
"""
类中方法:
种类:普通方法、类方法、静态方法、魔术方法
类方法:(@classmethod)
特点:
1. 定义需要依赖装饰器@classmethod
2. 类方法中参数不是一个对象,而是类
3. 类方法只可以使用类属性,无法访问对象属性
4. 类方法不依赖对象
5.不能使用普通方法
作用:
因为只能访问类属性和类方法,所以可以在对象创建之前,如果需要完成一些动作(功能),就可以方法类方法
静态方法:(@staticmethod)
类似于类方法
1. 需要装饰器staticmethod
2. 类中的静态方法无需传递参数(cls、self)
3. 也只能访问类的属性和方法,对象的无法访问
4. 加载时机同类方法
总结:
类方法 静态放啊
1、装饰器不同
2、类方法有参数、静态方法无参数
3、都可以通过类名i盗用
4、都可以再创建对象之前使用,因为是不依赖于对象。
普通方法 与类方法和静态的区别
1、没有装饰器
2、永远依赖对象
3、普通方法依赖对象,每个方法都有self
4、只有创建对象才可以调用、否则无法调用
"""
print("普通方法".center(30, "*"))
class Person:
birthday = "1992-11-01"
__dur_time = 100 # 前面加__ 私有
def __init__(self, name, age):
"""
定义共性特征:就是构造函数
:param name: 姓名
:param age: 年龄
"""
self.name = name
self.age = age
def eat(self, food):
print("{}正在吃{}!".format(self.name, food))
print("{}几岁了".format(self.age))
def run(self):
print("{}今年{}岁了,正在跑步!".format(self.name, self.age))
def info(self):
print("{}出生于{}".format(self.name, self.birthday)) # 建议使用self.birthday,而不是Person.birthday
@classmethod
def update_dur_time(cls):
"""
修改成员变量
:return:
"""
cls.__dur_time = 101
def get_update_dur_time(self):
return self.__dur_time
p = Person("张三", 18)
p.eat("红烧肉")
p.run()
p.name = '李四'
p.age = 28
p.eat("狮子头")
p.name = "Lucy"
p.info()
p.name = "Tony"
p.birthday = "1979-10-01"
p.info()
Person.update_dur_time()
result = p.get_update_dur_time()
print("消耗的时间{}".format(result))
print("类方法".center(30, "*"))
class Dog:
def __init__(self, nickname):
self.nickname = nickname
def run(self):
print("{}在院子中跑来跑去".format(self.nickname))
def eat(self):
print("吃饭。。。。。。。。。。。。")
self.run()
@classmethod
def test(cls): # cls class
print(cls) # <class '__main__.Dog'>
# print(cls.nickname) #报错
# print(self.nickname) #报错
print()
# cls.run() #报错
d = Dog("小黄")
d.run()
Dog.test() # L
print("静态方法".center(30, "*"))
class People:
def __int__(self, name):
self.name = name
@classmethod
def update_name(cls):
cls.__name__ = "葫芦娃"
@staticmethod
def show():
print("静态方法")
print("name =", People.__name__, sep=" ")
People.update_name()
People.show()
# __str__
"""
魔术方法:内置的函数,默认直接调用,如果需要改变返回值,需要重写
__str__ :
总结魔术方法:
__init__ __str__
了解
__new__ 开辟空间,
__del__ 没有指针调用的时候会调用 :一般不需要重写
"""
class Person:
# 不重写默认是None
def __init__(self, name, age):
self.name = name
self.age = age
# 魔术方法:重写了 :<__main__.Person object at 0x0000022DE5135B88>
def __str__(self):
print(self.name)
return "姓名:" + self.name + "年龄:" + str(self.age)
p = Person("张三", 18)
result = p.__str__()
print(result)
# 类方法
class Phone:
brand = '小米'
price = 2988
type = '米8'
# 魔术方法 :前后都有2个__名字__ (系统默认执行)
def __init__(self):
"""
初始化
"""
print("init....")
self.address_book = [] # 动态添加属性
def call(self): # self 是不断发生改变的
"""
self 就是对象
:return:
"""
print("self----------->", self)
print("正在打电话。。。。。。。")
print("正在访问通讯录。。。。。。。")
for person in self.address_book: # 不能保证每个self种保证address_book;所以有阴影
print(person.items())
xm = Phone()
print(xm.brand, xm.type, xm.price, sep=" ")
xm.address_book = [{"18799191912": "张三"}, {"18799191913": "李四"}]
print(xm)
print(xm.call())
hw = Phone()
hw.brand = '华为'
hw.type = 'mete 8'
hw.price = 3999
print(hw.brand, hw.type, hw.price, sep=" ")
print(hw)
print(hw.call())
print("*" * 30)
# 验证self
xm.note = '备注1:小米'
hw.note = '备注2:华为'
print(xm.note)
print(hw.note)
三性:封装、继承、多态
封装
"""
# 私有化:
__属性: 只能在类中赋值和修改, 访问权限进限制于类里边
好处:
隐藏属性,不被随意修改
可以通过提供的set_属性名()函数进行修改(对外的通用接口)
可以通过set_属性名()进行限制判断
# attribute:
get_age', 'get_name', 'set_age', 'set_name', 'set_score
'_Student__age', '_Student__name', '_Student__score'
封装:
私有化属性、定义公有的set get方法;
继承:
多态:
"""
class Student:
# __age = 19 # 类属性
# __score = 59
def __init__(self, name, age):
self.__name = name
self.__age = age
self.__score = 50
def __str__(self):
return "姓名是:" + self.__name + ",年龄:" + str(self.__age) + ",分数:" + str(self.__score)
# 定义公有的get和set方法
def set_age(self, age):
if age < 0 or age > 120:
print("年龄没有在合理范围内")
else:
self.__age = age
def get_age(self):
return self.__age
def set_score(self, score):
self.__score = score
def set_name(self, name):
if len(name) > 6:
print("名字长度不能超过六位")
else:
self.__name = name
def get_name(self):
return self.__name
s = Student("张三", 18)
print(s)
s.set_age(28)
print(s)
s1 = Student("李四", 20)
s1.set_age(128)
print(s1)
s1.set_name("tomorrow")
print(s1)
s1.set_name("lucy")
print(s1)
print(s1.get_name())
print(s1._Student__name) # 底层做了伪封装,不建议这么使用,建议通过set和get访问;_Student__name系统将私有化的属性修改的名称
print(dir(Student))
print(dir(s1))
继承
"""
has a:
在一个类中引用另一个自定义的类 :类如在student中使用computer
is a:(实类的判断) base class 父类 基类
系统类型
str int float
list dict tuple set
自定义类型:
s = Student() s 是student类型的对象
继承:
1、高内聚、降低重复代码
2、
特点:
1、如果类中不定义__init__,调用父类中 supper class 的__init__
2、如果类继承父类也需要定义自己的__init__,就需要在当前类__init__调用父类的__init__
3、如何调用父类__init__:
super().__init__(参数)
super(类名,对象).__init__(参数)
4、如果父类有eat(),子类也定义了一个eat方法,默认搜索的原则;先找当前类,再找父类:
t.eat()
override:重写(覆盖)
父类提供的方法无法满足子类的需求,需要子类定义一个同名的方法
5、
"""
class Computer:
def __init__(self, brand, type, color):
self.brand = brand
self.type = type
self.color = color
def on_line(self):
print("正在使用电脑上网")
def __str__(self):
return self.brand + "---" + self.type + "---" + self.color
class Book:
def __init__(self, book_name, author, number):
self.book_name = book_name
self.author = author
self.number = number
def __str__(self):
return self.book_name + "---" + self.author + "---" + str(self.number)
class Student: # has a
def __init__(self, name, computer, book):
self.name = name
self.computer = computer
self.books = []
self.books.append(book)
def borrow_book(self, book):
for bk in self.books:
if bk.book_name == book.book_name:
print("已经借过了")
else:
self.books.append(book)
print("添加成功了")
def show_book(self):
for book in self.books:
print(book.book_name)
def __str__(self):
return self.name + "---" + str(self.computer) + "---" + str(self.books)
computer = Computer("联想", "e430", "银色")
b = Book("盗墓笔记", "南派三叔", 10)
s = Student("张三", computer, b)
print(s)
bk = Book("鬼吹灯", "天下霸唱", 8)
s.borrow_book(bk)
print("-------------------------->")
s.show_book()
print("is a".center(30, "*"))
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(self.name + "正在吃饭......")
def run(self):
print(self.name + "正在跑步......")
class Employee(Person):
def __init__(self, name, age, salary):
super(Employee, self).__init__(name, age)
self.salary = salary
pass
class Teacher(Person):
def __init__(self, name, age, clazz):
"""
调用父类的init初始化
:param name: 姓名
:param age: 年龄
:param clazz: 班级
"""
super().__init__(name, age)
self.clazz = clazz
def attend_class(self):
print("{}老师正在上课,马上下课".format(self.name))
def eat(self):
"""
注意:
按照名称寻找,而不是像java一样根据参数判断
:return:
"""
print("子类正在重构父类的eat方法")
def __str__(self):
return "{}老师,今年{}岁,现在教{}班".format(self.name, self.age, self.clazz)
pass
e = Employee("张三", 18, 10000)
e.run()
e.eat()
t = Teacher("李四", 30, 5)
print(t)
t.attend_class()
t.eat()
# 继承 is a ;has a
"""
公路(road)
属性 公路名称 公路长度
车(car)
属性 车名 时速
方法:
1,求车名在那条公路上以多少时速行驶多长时间;
get_time(self,road)
2. 初始化车属性信息 init 方法
3. 打印对象显示车的属性信息
"""
import random
class Road:
def __init__(self, name, length):
self.__name = name
self.__length = length
@property
def length(self):
return self.__length
@property
def name(self):
return self.__name
class Car:
def __init__(self, brand, speed):
self.__brand = brand
self.__speed = speed
def get_time(self, road):
# ran_time = random.randint(1, 10)
ran_time = road.length/self.__speed
return "{}车,{},时速{},行驶{}小时".format(self.__brand, road.name, self.__speed, ran_time)
def __str__(self):
return "{},时速{}".format(self.__brand, self.__speed)
r = Road("丈八六路", 1200)
c = Car("大奔", 120)
result = c.get_time(r) # 传递对象
print(result)
print(c.__str__())
# 多继承
"""
允许多继承
1、广度优先原则:如果父类中有相同名称的方法,搜索顺序
python2 上面有区别
经典类: 从左至右,深度优先
新式类: 广度优先
python3上没有区别:就是广度优先
"""
import inspect
class A:
def test(self, a):
print("AA", a)
class B:
def test(self, b):
print("BB", b)
class C(A, B): # 解析顺序,就近原则
def test(self, c):
print("CC:", c)
print(inspect.getmro(C)) # 获取解析顺序
print(C.__mro__)
c = C()
c.test("c")
多态
# 多态
class Person:
def __init__(self, name):
self.__name = name
def feed_pet(self, pet):
# 判断pet是不是Pet得对象,或者pet是不是Pet子类的对象
if isinstance(pet, Pet):
print("{}喜欢喂养宠物{},{}".format(self.__name, pet.role, pet))
else:
print("不是宠物严禁饲养!")
pass
class Pet:
role = 'Pet'
def __init__(self, nickname, age):
self.__nickname = nickname
self.__age = age
def show(self):
print("昵称:{},年龄{}".format(self.__nickname, self.__age))
def __str__(self):
return "昵称:{},年龄{}".format(self.__nickname, self.__age)
class Cat(Pet):
role = '猫'
def catch_mouse(self):
print("抓老鼠")
class Dog(Pet):
role = '狗'
def watch_house(self):
print("看家护院")
class Tiger:
def eat(self):
print("太可怕了,可以吃人")
c = Cat("小花", 3)
d = Dog("小黄", 4)
p = Person("张三")
p.feed_pet(c)
p.feed_pet(d)
t = Tiger()
p.feed_pet(t)
单例
# 开发模式
"""
开发模式:
单例模式: 对内存的优化
"""
class Student:
pass
class Singleton:
# 私有化类属性,单例的地址存在这个属性
__instance = None
name = 'Java'
# 重写父类:
def __new__(cls, *args, **kwargs):
print("--new--")
if cls.__instance is None:
cls.__instance = object.__new__(cls)
return cls.__instance # 扔给底层的__init__
def show(self, n):
print("--------->", Singleton.name, n)
s1 = Student()
print(s1) # <__main__.Student object at 0x0000018FAD915FC8>
s2 = Student()
print(s2) # <__main__.Student object at 0x0000018FAD915F48>
st1 = Singleton()
print(st1) # <__main__.Singleton object at 0x0000023FAB56F0C8>
st1.show(5)
st2 = Singleton()
print(st2) # <__main__.Singleton object at 0x0000023FAB56F0C8>
st2.show(7)
print(dir(Singleton))
练习
class Person:
def __init__(self, card, name, salary):
"""
:param card: id
:param name: 姓名
:param salary:薪水
"""
self.__card = card
self.__name = name
self.__salary = salary
# 注意先get、再set
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
def get_card(self):
return self.__card
def salary(self):
return self.__salary
def __str__(self):
return "工号:{},姓名:{},薪资:{}".format(self.__card, self.__name, self.__salary)
class Worker(Person):
def __init__(self, card, name, hour, hour_salary):
super(Worker, self).__init__(card, name, hour * hour_salary)
"""
:param hour: 工作小时
:param hour_salary: 时薪
"""
self.__hour = hour
self.__hour_salary = hour_salary
class SelaMan(Person):
def __init__(self, card, name, sales, commission):
super(SelaMan, self).__init__(card, name, sales * commission)
"""
:param sales: 销售额
:param commission: 提成比例
"""
self.__sales = sales
self.__commission = commission
self.__salary = sales * commission
def salary(self):
return self.__salary
class Manager(Person):
def __init__(self, card, name, month_salary):
"""
:param card: 身份id
:param name: 姓名
:param month_salary: 月薪
"""
self.month_salary = month_salary
super().__init__(card, name, month_salary)
def salary(self):
return self.month_salary
class SaleManager(SelaMan):
def __init__(self, card, name, sales, commission, month_salary):
self.__month_salary = month_salary
self.__sales = sales
self.commission = commission
super().__init__(card, name, sales, commission)
def salary(self):
return self.__month_salary + self.__sales * self.commission
w = Worker(1, "张三", 168, 50)
print("工人工资:", w.salary())
print(w)
s = SelaMan(2, "李四", 500000, 0.1)
print("销售人员工资:", s.salary())
print(s)
m = Manager(3, "王五", 20000)
print("管理人员工资:", m.salary())
print(m)
sm = SaleManager(4, "赵六", 50000, 0.1, 25000)
print("销售主管工资:", sm.salary())
print(sm)