今日内容

对象的独有功能

针对对象独有的方法 我们无法真正实现
如果在全局则不是独有的
如果在类中则是公共的
python解释器针对上述问题添加了一个非常牛的特性
定义在类中的函数默认是绑定给对象的(相当于是对象独有的方法)

class Person:
    h_type = '人类'

    def __init__(self, name):  # 让对象拥有独有的数据
        self.name = name

    # 定义在类中的函数 我们称之为方法
    def eat(self): # 是多个对象公共的方法 也算多个对象独有的方法  对象来调用就会将对象当做第一个参数传入
        print('%s正在努力学习' % self.name)

    def others(self, name, b):
        print('%s好困,好想睡觉'%self.name)


p1 = Person('joker')
p1.eat()  # joker正在努力学习
p2 = Person('oscar')
p2.eat()  # oscar正在努力学习

# 如何理解绑定二字
# 绑定只针对对象,对象来调这个方法不需要传参数
# 但是其他人来调有几个参数就要传几个参数
p3 = Person('lisa')
Person.eat(p3)  # lisa正在努力学习

p4 = Person('joker')
p4.others(1, 2)  # joker好困,好想睡觉

Person.others(p4, 1, 2)  # joker好困,好想睡觉

动静态方法

专门针对在类体代码中编写的函数

一、绑定给对象的方法
直接在类体代码中编写即可
对象调用会自动将对象当做第一个参数传入
类调用则有几个形参就传几个实参

class Person:
    h_type = '人类'
    def __init__(self, name):
        self.name = name
    def others(self, name, b):
        print('%s好困,好想睡觉'%self.name)
# 如何理解绑定二字
# 绑定只针对对象,对象来调这个方法不需要传参数
# 但是其他人来调有几个参数就要传几个参数
p3 = Person('lisa')
Person.eat(p3)  # lisa正在努力学习

p4 = Person('joker')
p4.others(1, 2)  # joker好困,好想睡觉

二、绑定给类的方法

class Student:
    school = '北京大学'

    # 绑定给对象的方法
    def run(self):  # self用于接收对象
        print('跑的真快')

    @classmethod # 绑定给类的方法
    def eat(cls):  # cls用于接收类
        print('你可真有才')
    @staticmethod # 静态方法
    def sleap(a,b):
        print('赶紧去睡觉')

stu1 = Student()
# 调用绑定给类的方法
# 类调用会自动将类当做第一个参数传入  等价于eat(Student)
Student.eat()  # 你可真有才
# 对象调用会自动将产出该对象的类当做第一个参数传入  等价于eat(Student)
stu1.eat()  # 你可真有才

三、静态方法(普普通通的函数)@staticmethod

# 调用静态方法
stu1 = Student()
# 当staticmethod装饰后的方法(函数)不管是谁来调 有几个形参就要传几个
Student.sleap(1,2)  # 赶紧去睡觉
stu1.sleap(1,2)  # 赶紧去睡觉

面向对象三大特性之继承

面向对象三大特性分别是
继承、封装、多态

一、继承的含义

在现实生活中继承其实就是用来描述人与人之间资源的关系
    eg:儿子继承父亲的财产(拥有了父亲所有的资源)
在编程世界里继承其实就是用来描述类与类之间数据的关系
    eg:类A继承类B(拥有了类B里面所有的数据和功能)

二、继承的目的

现实生活中继承就是想占有别人的财产
    eg:亲身父亲 干爹 干妈 富婆
编程世界里继承就是为了节省代码编写
    eg:可以继承一个类 也可以继承多个类

三、继承的操作

class 类名(类名):
  pass
      1.定义类的时候在类名后加括号
      2.括号内填写你需要继承的类名
      3.括号内可以填写多个父类 逗号隔开即可
      """
      我们将被继承的类称之为: 父类或基类或超类
      我们将继承类的类称之为: 子类或派生类
      ps:平时最常用的就是父类和子类
      """
class MyClass(父类1,父类2,父类3,...):
   pass

ps:目前掌握从左到右查找每个父类中的属性即可

继承的本质

抽象:将多个类共同的数据或功能抽取出来形成一个基类

继承:从上往下白嫖各个基类里面的资源

对象:数据和功能的结合体
类:多个对象相同的数据和功能的结合体
父类:多个类相同的数据和功能的结合体
ps:类和父类最主要的功能其实就是节省代码
一定要掌握继承的本质 这样以后你才会在代码中自己定义出子类父类

class Person:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
class Teacher(Person):
    def teach_course(self):
        print('老师正在上课')
class Student(Person):
    def choice_course(self):
        print('学生正在选课')

stu = Student('jason',18,'male')
print(stu.__dict__)  # {'name': 'jason', 'age': 18, 'gender': 'male'}

提取子类共同特征得到父类的过程叫抽象

基于抽象的结果我们就找到了继承关系

名称的顺序查找

一、在不继承的情况下名字的查找顺序
先从对象自身查找 没有的话 在去产生该对象的类中查找

 class Student:
     school = '北京大学'
     def choice_course(self):
         print('正在选课')
stu1 = Student()
# 对象查找school 自身空间没有 所有查找的是类里面的
print(stu1.school)  # 北京大学

# 在自身空间产生了新的school
# 对象点名字并写了赋值符号和数据值 那么操作的肯定是自己的名称空间
stu1.school = '交通大学'
print(stu1.school)  # 交通大学

print(Student.school)  # 北京大学
# 查找顺序 对象>>>类

二、单继承的情况下名字的查找顺序
先从对象自身查找 然后是产生该对象的类 然后是一个个父类

class A:
    name = 'from A'
class B(A):
    name = 'from B'
class C(B):
    name = 'from C'
class MyClass(C):
    name = 'from MyClass'

obj = MyClass()
# obj.name = '好想睡觉'
print(obj.name)
# 顺序查找 对象自身>>>类>>>父类
# 先是在obj自身查找 如果obj自身没有在到MyClass MyClass没有在到C C没有在到B B没有在到A A没有则会报错

class A1:
    def func1(self):
        print('from func1')
    def func2(self):
        print('from func2')
        self.func1()
class MyClass(A1):
    def func1(self):
        print('from MyClass func1')
obj = MyClass()
obj.func2()
# 结果为 from func2
# from MyClass func1
只要涉及到对象查找名字 几乎要回到最开始(自身)依次查找

三、多继承的情况下名字的查找顺序

  1. 非菱形继承(最后不会归总到一个我们自定义类上)
    深度优先(每个分支都走到底 再切换)

  1. 菱形继承(最后归总到一个我们自定义类上)
    广度优先(前面几个分支都不会走最后一个类 最后一个分支才会走)

可以使用类点mro()方法查看该类产生的对象名字的查找顺序
也可以使用类点__bases__方法查看当前这个类继承了那些父类

经典类与新式类

经典类
	不继承object或其子类的类(什么都不继承)
新式类
	继承了object或其子类的类
	eg:
        class MyClass:  # 等价于class MyClass(object):pass
             pass
"""
在python3中所有的类默认都会继承object
    也就意味着python3里面只有新式类

在python2中有经典类和新式类
    由于经典类没有核心的功能 所以到了python3直接砍掉了
	
以后我们在定义类的时候  如果没有想要继承的父类 一般推荐以下写法
    class MyClass(object):
        pass

目的是为了兼容python2
"""
以后写代码针对object无需关心 知道它的存在即可

派生方法

子类中定义类与父类一模一样的方法并且扩展了该功能>>>:派生
如果我们自己写的子类需要用到父类的方法 并且还需要基于该方法做扩展
那么我们可以使用关键字来实现 super()

方式一、

# 父类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

# 子类
class Teacher(Person):
    def __init__(self, name, age, gender, level):
        Person.__init__(self, name, age, gender)  # 先调用父类的方法
        self.level = level  # 自己可以在补充一些

方式二、
使用关键字:super()

# 父类
class Person:
    def __init__(self, name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
# 子类
class Teacher(Person):
    def __init__(self,name,age,gender,level):
        super().__init__(name,age,gender)  # super专门用于子类调用父类的方法
        self.level = level  # 自己可以在补充一些

小案例、
使用派生方法 我们可以在列表做一些额外的操作

class MyClass(list):
    def append(self,values):
        if values == 'joker':
            print('joker不能追加')
            return
        super().append(values)

obj = MyClass()
obj.append(11)
obj.append(22)
obj.append('joker')
obj.append(33)
print(obj)  # [11, 22, 33]
 posted on 2022-07-27 20:43  Joker_Ly  阅读(56)  评论(0)    收藏  举报