美文网首页
24.面向对象(类、封装)

24.面向对象(类、封装)

作者: 哈哈大圣 | 来源:发表于2019-12-27 21:21 被阅读0次

面向对象(类、封装)

一、类与实例对象

1). 类的定义与实例化

  1. 实例化之前先定义类,类名要大写 (解释性语言特点)
class Student:
    # Python很奇葩:这里定义为静态数据变量
    name = '哈哈大圣'   # 静态数据属性:

    def learn(self):   # 函数属性
        print('is learning')

    def eat(self):     # 函数属性
        print('is sleeping')
  1. 实例化对象
stu1 = Student()
print(stu1)

2). 类内元素操作

  1. 查看类的名称空间
a = Student.__dict__
name = Student.__dict__['name']
learn = Student.__dict__['learn']
  1. 获取类的属性
name = Student.name    # 等同于Student.__dict__['name']
learn = Student.learn  # 等同于Student.__dict__['learn']
  1. 增加类的属性,可以增加成员属性,也可以增加函数属性;(解释性语言特点)
Student.county = 'China'

def like():
    print("like")
Student.like = like
Student.like()
  1. 修改类的属性
Student.school = '双一流大学'
  1. 删除类的属性
del Student.county
del Student.like

3). 构造函数

  1. __init__: 用来为对象定制对象自己独有的特征
    • 此方法中定义才为实例变量
class Student: #定义的时候执行该类

    school='双一流大学'

    def __init__(self, name, sex, age):
        self.Name=name
        self.Sex=sex
        self.Age=age

    def learn(self):
        print('is learning')

    def eat(self):
        print('is sleeping')
  1. 执行定义的构造函数
stu1=Student('王二丫','女',18) 
# 等同于Student.__init__(stu1,'王二丫','女',18)

4). 类方法、普通方法以及数据属性

  1. 调用普通方法,方法所在的地址都是一样的
  2. 对象中的绑定方法与对象之间进行绑定,不同的对象相同的绑定方法所占的内存地址是不一样的。
  3. 通过.访问的数据属性,会先在对象命名空间找,没有就在类的命名空间找,在没有就在父类中去找,但不会到所在模块中去找了,这是类的特性

二、继承

1). Python中的继承

  1. 支持多继承,通过C3线性查找算法生成一个MRO列表,根据列表顺序查找
  2. 继承的语法
class A:
    name = "A"
    
    def func(self):
        print("A func")

class B:
    name = "B"
    
    def func(self):
        print("B func")

# 继承的写法
class C(A, B):
    name = "C"
    
    def func(self):
        print("B func")

2). 派生

  1. 派生,重写父类的方法或者属性
  2. 案例
class Hero:
    def __init__(self, name, life_count, attact_count):
        self.name = name
        self.life_count = life_count
        self.attact_count = attact_count

    def attact_enemy(self, enemy):
        enemy.life_count -= self.attact_count

# 加个括号表示继承
class Galen(Hero): 
    # 当子类中重写了父类的方法之后,就会调用子类的方法,这就叫做派生
    def attact_enemy(self): 
        print("攻击无效")

class Ruiwen(Hero):
    pass
    
g1 = Galen("草丛伦",100,30) #生成一个对象
r1 = Ruiwen("瑞文妹妹",80,50)
g1.attact_enemy()

3). C3线性查找算法

  1. 经典类的查找方式

经典类.png
  1. 新式类 (Py3中的类) 的查找方式:C3线性查找算法
    • 根据继承关系生成对应的图,根据相应的图算法确定顺序。
    • 很明显,如果多个分支有共同的父类,会将此父类的遍历位置放在其他分支的深度优先遍历之后。

新式类.png
  1. 任何父类中查找的起始点为发起方法/数据属性的子类所在的内存空间。
temp = "temp"
class Hero:
    def f1(self):
        print("Hero's f1")

    def f2(self):
        print("Hero's f2")
        self.f1()        # 注意,这里又开始从对象中开始查找了
        print(self.nice) # 注意,这里又开始从对象中开始查找了
        print(temp)      # 这个temp不是用.调用的,不和对象产生关系,所以查找的方式是普通的命名空间的规则

class Galen(Hero):
    def __init__(self):
        self.nice  = "nice"
        
    def f1(self):
        print("Galen's f1")

g1 = Galen()
g1.f2()
"""
Hero's f2
Galen's f1
nice
temp
"""
  1. 查看父类
class Foo:
    pass

print(Foo.__bases__) #查看父类

print(Foo.mro()) #打印MRO列表(经典类没有这个方法)

4). 子类中重用父类的方法属性

  1. 子类中重用父类的方法和属性有两种方式
    1. 指名道姓(不依赖继承)
    2. super(): (依赖继承,基于对象所产生的MRO列表)

class Hero:
    def __init__(self,nickname, life_value, aggresivity):
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
        
    def attack(self, enemy):
        enemy.life_value -= self.aggresivity


class Garen(Hero):
    camp='Demacia'
    def __init__(self, nickname, life_value, aggresivity):
        # 依赖性继承的方式,py3中的简写方式(找MRO)
        super().__init__(nickname, life_value, aggresivity)

    def attack(self, enemy):
        # 指名道姓重用父类的方法,不依赖于继承
        Hero.attack(self, enemy)   
        print('from Garen Class')

class Riven(Hero):
    camp='Noxus'

g = Garen('草丛伦',100,30)
r = Riven('锐雯雯',80,50)

三、组合

1). 组合概述

  1. 组合描述的是 has a 关系
  2. 对于类数据属性,通过实例对象“.”的方式进行数据子元素的增删改,如果没有实例变量则会找静态变量。
  3. 通过实例.数据属性 = ?这种形式,则此数据属性为对象属性,非静态的。
import datetime
class Person:
    def __init__(self,name,gender,date):
        self.name = name
        self.gender = gender
        self.date = date
        self.age = self.calculate_age()

    def calculate_age(self):
        time_lag = datetime.datetime.now().year - self.date.date_struct.year
        return time_lag

class Student(Person):
    course_list = [] # 静态变量
    def __init__(self,name,gender,date,course):
        super().__init__(name,gender,date)
        Student.course_list.append(course)  # 这么写了就成了静态变量了

    def learning_course(self):
        print("%s is learing!" % self.name)

class Teacher(Person):
    pass

class Date:
    def __init__(self,year,month,day):
        self.date_struct = datetime.datetime.now().replace(year=year,month=month,day=day)

    def show_info(self):
        print("%s年%s月%s日" % (self.date_struct.year,self.date_struct.month,self.date_struct.day))

d1 = Date(1996, 12, 12)
s1 = Student("a", "male", d1, "python")

# 通过对象直接增删改,对象没有则找静态变量
s1.course_list.append("python进阶")

# 直接赋值,数据属性属于对象。
s1.course_list = ["art"]

# 通过组合的方式调用了其他类中的属性(组合关系,非继承关系)就是有的关系
s1.date.show_info()

相关文章

  • 24.面向对象(类、封装)

    面向对象(类、封装) 一、类与实例对象 1). 类的定义与实例化 实例化之前先定义类,类名要大写 (解释性语言特点...

  • 面试 | java基础

    面向对象 1、面向对象特征? 封装封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成...

  • 「JAVA」- 知识点小结

    java面向对象编程 面向对象(概念): 三大特性: 封装: 封装,就是把客观事物封装成抽象的类,并且类可以把自己...

  • Java_类和对象

    面向对象的三大特点:封装、继承、多态封装:封装是面向对象的核心思想。将对象的属性和行为封装起来。其载体就是类,类通...

  • Scala入门与进阶(四)- Scala面向对象

    Scala面向对象 1.面向对象概述 封装:属性方法封装到类中 继承:父类和子类直接的关系 多态:***** 父类...

  • 面对对象程序(二)

    面向对象三大特性: 1. 封装 封装是面向对象编程的核心思想。封装的载体是类,对象的属性和行为被封装在这个类中。例...

  • 面向对象核心技术

    面向对象核心技术 面向对象编程有3大基本特性:封装、继承和多态。 (1)类的封装:封装是面向对象编程的核心思想。封...

  • 面向对象, equals与 ==区别演示,print与print

    一. 面向对象 1.理解面向对象的概念 类与对象 三大特征:封装示例封装演示 面向对象: 在调用对象时,除了要指定...

  • 面对对象高级编程

    面向对象高级编程: 面向对象编程:封装、继承和多态 面向对象高级编程:多重继承、定制类和元类

  • Python

    一、面向对象(类、对象) 1、面向过程:面向对象:根据职责确定对象,在对象内封装不同方法根据类来创建的对象呗称为实...

网友评论

      本文标题:24.面向对象(类、封装)

      本文链接:https://www.haomeiwen.com/subject/jncjoctx.html