Python基础6——面向对象

14 面向对象

14.1 面向对象基础

​ 面向对象是一种编程思想,处理面向对象编程以外,还有面向过程编程

三大特征:

1. 封装
2. 继承
3. 多态

面向过程与面向对象的区别

  1. 面向过程: 自己动手洗衣服,拧衣服、晾衣服
  2. 面向对象:构造一个洗衣机对象,让洗衣机对象完成

14.2 类和对象

:相同属性和功能的一类事物。

​ 人是一个,张三(对象),李四(对象),王五(对象)

​ 狗是一个,张三的柯基(对象),张三的哈士奇(对象),王五的田园犬(对象)

类的写法

class 类名:
    pass

# 一般首字母大写,使用驼峰命名法。

​ 类的三要素

  1. 类名
  2. 属性
  3. 方法

class Human:
    hair = 'gold'

print(Human.hair)
Human.hair = 'black'
print(Human.hair)
Human.name = '比尔盖茨'
del Human.hair  #删除属性

实例化对象

执行实例方法时,自动将调用该方法的对象赋值给self

# 实例化对象的格式: 对象名 = 类名()
# 实例方法:由对象来调用,至少一个self参数;
# 执行实例方法时,自动将调用该方法的对象赋值给self

class Person:
    name = "zhangsan"
    def speak(self):
        print("self")
        print(self) #这里的self就是当前调用函数的对象
        print("正在说话")
	

p1 = Person()
print(p1)

p1.speak()

14.3 构造方法

实例属性: self.属性名


class A:
    name = 'zhangsan' #类属性
    
    def work(self): #实例方法
        print("实例方法")
        print(f"张三的年龄是{self.age}")

a = A()
a.age = 20
a.work()

构造方法

类在实例化的时候,会自动执行init方法


class A:
    def __init__(self,name):
        self.name = name

a = A("张三")
print(a.name)


class Hero:
    def __init__(self,name,hp,at):
        self.name = name
        self.hp = hp
        self.at = at
    
    def move(self):
        print(f"{self.name}在移动")
    def attack(self):
        print(f"{self.name}的生命值是{self.hp}")

 # 实例化对象
libai = Hero("李白",2000,120)
libai.move()
libai.attack()

luban = Hero("鲁班",2100,200)
luban.move()
luban.attack()

14.4 类属性和实例属性

总结:

  1. 类属性属于类,实例属性属于对象

  2. 实例属性属于每个对象,对象不同实例属性不同。实例属性需要添加self

class A:
    num = 10 #类属性
    def __init__(self,name):
        self.name = name #实例属性
    def test(self):
        print(f"我是{self.name}")
  

# 第一次实例化对象
a = A("张三")
a.test()
print(A.num)  #通过类名查看类属性
print(a.num)  #通过对象查看类属性
print(a.name)  #通过对象查看实例属性

# 第二次实例化对象
a1 = A("李四")
a1.test()
print(a1.name)
print(a1.num)


14.5 析构方法

当对象被垃圾回收的时候,解释器会默认调用del的方法。

class A:
    def __del__(self):
        print("执行析构方法")
a = A()
print("打印最后一句")

# 运行结果
# 打印最后一句
# 执行析构方法

class A:
    def __del(self):
        print("执行析构方法")
a = A()
del p
print("打印最后一句")

# 运行结果
# 执行析构方法
# 打印最后一句


14.6 封装

14.6.1 封装的概念

将复杂的信息、流程给包起来,内部处理,让使用者只需要通过简单的操作步骤,就能实现。

封装的概念:

  1. 类 ,本身就是一种封装
  2. 类中定义私有,只在类的内部使用,外部无法访问

14.6.2 私有属性

​ 私有权限:在属性名和方法名前加上两个下划线

class Person: 
    name = "jiuge" #类属性
    __age = 18  #类的私有属性
    

a = Person()
print(a.name)
print(a.__age) #会报错
# 私有属性:外部不能直接访问

# 如何访问私有属性,不建议使用
# 第一种方式
# _类名__属性名
print(pe._Person__age)

# 第二种方式
class Person:
    name = "jiuge"
    __age = 18
    
    def getAge(self): #获得私有属性的方法
        return Person.__age

pe = Person()
print(pe.getAge())


14.6.3 私有方法、proteted方法

_xx : 单下划线开头,protected属性/方法,在对象和子类可以访问,其实并没有什么卵用

__xx : 双下划线开头,私有权限,无法在外部直接访问

class Person:
    name = "jiuge" #类属性
    _sex = '女'   #protected方法
    __age = 18    # 私有属性
a = Person()

print(a._sex) #可以访问
print(a.__age) #不可以访问

私有方法

双下划线开头

class Human:
    def __play(self): #私有方法
        print("玩手机")
	
    def funa(self):  #实例方法
        # 不推荐
        # Human.__play(self)  #在实例方法中调用私有方法
        
        self.__play() #直接用这个就可以了

ha = Human()
ha.__play() #会报错
ha.play() #会报错
ha.funa()  

14.7 继承(单继承、多继承)

14.7.1 单继承的例子

继承可以使子类具有父类的所有属性和方法

语法:class 类名(父类名)

class A:
    def __init__(self):
        self.age = 18
    def add(self):
        print(self.age+10)

class B(A): #B类继承A类
    pass

b = B()
print(b.age)
b.add()


class Animals: #父类
    def eat(self):
        print("吃")
	def sleep(self):
        print("睡")
        
class Pig(Animals):#子类
    pass

class Dog(Animals): #子类
    pass

pig = Pig() #实例化子类
pig.eat()
pig.sleep()

dog = Dog() #实例化子类
dog.eat()
dog.sleep()


14.7.2 单继承的传递性

如果C类(子类)继承于B类(父类),B类(子类)继承于A类(父类)

那么C类具有A类、B类的属性和方法


class A:
    def eat(self):
        print("吃")
    def sleep(self):
        print("睡")

class B(A): #继承于A类
    def study(self):
        print("学习")

class C(B): #继承于B类
    pass

b = B()
b.eat()
b.study()


c = C()
c.study() #调用父类的方法
c.eat()  #调用父类的父类的方法

14.7.3 多继承

python中内置属性__mro__可以查看方法搜索顺序

确定子类对象调用方法的顺序

print(Son.__mro__)

# 打印执行方法的顺序
print(C.__mro__)

子类拥有所有父类的属性和方法

class A:
    def eat(self):
        print("吃")

class B:
    def sleep(self):
        print("睡")
class C(A,B): #C多继承A类和B类
    pass

c = C()
c.eat()
c.sleep()

若D类继承于A类、B类

则D会先找A类中的方法,如果找不到再找B类的方法

class A:
    def h(self):
        print("a")
class B:
    def h(self):
        print("c")

class C(A,B):
    pass

c = C()
c.h()
# 输出结果
# a

class D(B,A):
    pass
# 输出结果
# c

查找顺序 D->A->B->C

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y3SN4NnR-1625891783101)(https://img2020.cnblogs.com/blog/1466380/202006/1466380-20200604210907285-1409082663.png)]

查找顺序D->B->A->C

查找顺序E->B->A->D->C

s

查找顺序 E->B->A->D->C->F

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DH3Pofj4-1625891783106)(https://img2020.cnblogs.com/blog/1466380/202006/1466380-20200604212718837-1012657606.png)]

14.7.4 继承的例子

奥特曼的例子

#奥特曼

# 一代产品
class Aoteman(object):
    def __init__(self,year,name):
        self.year = year
        self.name = name
        
    def speak(self):
        print(f"{self.name}说,爱是一道光")
        
    def attack(self):
        print(f"{self.year}年的{self.name}会发光")
        
at = Aoteman(1996,"初代奥特曼")
at.speak()
at.attack()


# 二代奥特曼
class Aoteman2(Aoteman): #继承一代奥特曼的特性
    def attack(self):
        print(f"{self.year}年的{self.name}会投飞镖")
        
at2 = At2(1998,"赛文")
at2.speak()
at2.attack()


# 三代奥特曼
class At3(object):
    
    def defend(self): #防御
        print("会躲避怪兽的攻击")

class Aoteman3(Aoteman,At3): #多继承
    def attack(self):
        print(f"{self.year}年的{self.name}奥特曼会光之射线")
    
    def color(self):
        print(f"{self.name}奥特曼会变色")
 
at3 = Aoteman3(2000,'迪迦')
at3.speak()
at3.attack()
at3.color()
at3.defend()

14.8 重写

子类继承父类的方法和属性,对父类的方法和属性进行重写

14.8.1 覆盖父类方法

​ 在子类中定义一个跟父类同名的方法


class Person:#父类
    def work(self):
        print("接受社会的考验")

class Son(Person): #子类
    def work(self):
        print("接受社会的毒打")

son = Son()
son.work()
# 运行结果
# 接受社会的毒打


14.8.2 对父类的方法进行扩展:

继承父类的方法,子类可以增加自己的功能

实现方法

  1. 父类名.方法名(self)
  2. super().方法名()

父类名.方法名(self)


class Person:
    def work(self):
        print("接受社会的考验")
class Son(Person):
    def work(self):
        Person.work(self)
        print("接受社会的毒打")

son = Son()
son.work()

super().方法名()

super是一个特殊的类,super()是使用super类创建出来的对象,可以调用父类中的方法


class Animal:
    def __init__(self,name):
        self.name = name
    
    def bark(self):
        print(f'{self.name}在叫')
        
class Dog(Animal):#子类
    def bark(self):
        super().bark()  #父类的方法
        print(f"{self.name}在汪汪叫")  #在父类的方法上进行扩展

dog = Dog('哈士奇')
dog.bark()

14.8.3 多继承中的重写

多继承的重写,根据广度优先搜索进行执行

14.9 新式类写法,object类

# 写法一
class A:
    pass
# 写法二
class A():
    pass
# 写法三,推荐
class A(object):
    pass

object是为所有对象提供的基类,提供了一些内置的属性和方法

14.10 多态

14.10.1 多态基础

python中的多态是一个伪多态

​ 一个对象具有多种形态,在不同的使用环境中以不同的形态展示其功能,那么我们就称该对象具有多态特性。

多态发生在具有继承关系的基础之上

不关注对象的类型,关注对象具有的行为

不同的子类对象,调用相同的父类方法,会产生不同的执行结果


# + 同样的+号,不同的对象使用,就会有不同的结果
print(10+10)
print("10"+"10")

class Animal(object):
    def walk(self):
        print("动物在走路")
	
class Cat(Animal):
    def walk(self):
        print("走猫步")
miao = Cat()
miao.walk() 
# 输出结果
# 走猫步

class People(Animal):
    def walk(self):
        print("两条腿走路")
people = People()
people.walk()
# 输出结果
# 两条腿走路

14.10.2 多态性

一种调用方式,不同的执行结果

指具有不同功能的函数可以使用相同的函数名,把对象作为参数传入

class A(object): #父类
    def speak(self):
        print("群众的眼睛是雪亮的")
        
class C1(A):  #子类1
    def speak(self):
        print("年轻人不讲武德")

class C2(A):  #子类2
    def speak(self):
        print("心疼giegie")

def test(obj): #定义一个函数,把对象作为参数传入
    obj.speak()

c1 = C1()
# c1.speak()
test(c1)  
# 输出结果
# 年轻人不讲武德

c2 = C2()
# c2.speak()
test(c2)
# 输出结果
# 心疼giegie

14.11 类方法和静态方法

实例方法:方法内部访问实例属性,方法内部可以通过类名.类属性来访问类属性

静态方法:方法内部,不允许访问实例属性,类属性可以通过类名调用。但是不推荐这么使用

类方法:方法内部只允许访问类属性,通过cls.类属性访问

14.11.1 静态方法

使用@staticmethod符号进行定义

class 类名:
    @staticmethod  #定义为静态方法
    def 方法名(形参):
        方法体
# 调用格式
类名.方法名(参数)
对象名.方法名(参数)


class Dog(object):
    
    @staticmethod #静态方法:类中的函数。可以用类名调用类属性,但是不推荐。
    def run():
        print("狗狗在跑步")

Dog.run()

14.11.2 类方法

使用@classmethod符号进行定义

针对类对象定义的方法

class 类名
	@classmethod #类方法
    def 方法名(cls): #出现cls参数
        方法体

class Cat(object):   
    name = '布偶'  #类属性
    
    @classmethod  #类方法
    def sleep(cls): #这里的cls是指Cat这个类
        print(cls)
        print("猫猫在睡觉")

print(Cat)
Cat.sleep()
# 输出结果
# <class '__main__.Cat'>
# <class '__main__.Cat'>
# 猫猫在睡觉

14.12 魔法方法

魔法方法有很多,这里只举4个例子

__doc__   #类的描述信息
__module__  #表示当前操作的对象在哪个模块
__class__  # 表示当前操作的对象的类是什么
__str__  #对象的描述信息

14.12.1 __doc__方法


class A:
    '''  
    这是类的描述信息
    '''
    # 必须要使用'''来表示
    pass

print(A.__doc__)

# 这是类的描述信息

14.12.2 __str__方法

# 如果类中定义了__str__方法,那么在打印实例化对象,默认输出该方法的返回值

# str方法必须返回一个字符串
class A:
    def __str__(self):
        return "类似于java的toString方法"
a = A()
print(a)

14.12.3 __module__ 、__class__ 方法

pytest.py 
class C:
    def funa(self):
        print("这是C类的实例方法")
        
      
main.py
import pytest
pt = pytest.C()
print(pt)
pt.funa()

print(pt.__module__) #输出结果: pytest 所在模块
print(pt.__class__)  #<class 'pytest.C'>


14.12.4 __eq__

判断两个类是否相等,返回bool值

14.12.4 __hash__

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值