今日内容回顾

对象的独有功能

针对对象独有的功能,我们无法真正实现

定义在类里面的方法,原则上是公共的方法

但其本质是那个对象调用属于那个对象独有的功能。

示例:

# 首先定义一个类
class Student:
    # 在类中定义的数据属于公共的数据,在类中定义的函数属于公共方法
    school = '清华大学'

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

    # 定义在类中的函数,我们称之为方法
    def choice_course(self):
        print('%s正在选课' % self.name)

stu = Student('jason')
stu1 = Student('jack')
# 1.在全局给对象独自添加一个功能。
def func():
    print("我在全局")
# 2.将功能添加给对象
stu.func = func
# 3.但是如果在全局也不是独有的
stu.func()
# 谁调用类中的方法就属于谁的独有的功能
stu.choice_course()  # jason正在选课
stu1.choice_course()  # jack正在选课


"""
因此python解释器在针对这类问题添加了一个非常哇塞的特性
定义在类中的函数默认是绑定给对象的(相当于是对象独有的方法)
"""

动静态方法

动静态方法专门针对在类体代码中编写的函数

  1. 绑定给对象的方法

    直接在类体代码中编写即可

    对象调用会自动将对象当作第一个参数传入,类调用则有几个形参就需要传几个实参。

    class Student:
        # 在类中定义的数据属于公关的数据,在类中定义的函数属于公共方法
        school = '清华大学'
    
        # 定义在类中的函数,我们称之为方法
        def choice_course(self):
            print('正在选课')
    
    stu = Student()
    
    
    """
    对象在调用类中的方法,会自动将对象当作第一个参数传入
    后面需要几个参数,在根据数量传入即可
    """
    stu.choice_course()  # jason正在选课
    # 类在调用类中的方法,里面需要几个参数则传入几个参数
    Student.choice_course(111)
    
    
  2. 绑定给类的方法

    在类体代码方法上面加入装饰器@classmethod

    类调用会自动将类当作第一个参数传入,对下个调用会自动将产生对象的类当作参数传入

    class Student:
        # 在类中定义的数据属于公关的数据,在类中定义的函数属于公共方法
        school = '清华大学'
    	
        @classmethod  # 绑定给类的方法
        def choice_course(cls):  # cls用于接收类
            print('正在选课')
    
    stu = Student()
    Student.choice_course()  # 相当于 Student.choice_course(Student)
    stu.choice_course()  # stu.choice_course(Student)
    
  3. 静态方法

    在类体代码方法上面加入装饰器@staticmethod

    无论谁来调用都必须按照普普通通的函数的传参方式

    class Student:
        # 在类中定义的数据属于公关的数据,在类中定义的函数属于公共方法
        school = '清华大学'
    
    
        @staticmethod  # 静态方法
        def choice_course(a,b):  # 普通的函数传承
            print('正在选课')
    stu1 = Student()
    Student(111,222)
    stu1.sleep(1, 2)
    

面向对象三大特性之继承

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

  • 继承的含义

    在现实生活中,继承用来描述人与人之间的资源关系,比如子承父业,(儿子也拥有了父亲所有的资源)

    而编程世界里,继承其实就是用来描述类与类之间数据的关系,比如类A继承了类B(拥有了类B里面所有的数据和功能)

  • 继承的目的

    继承的目的就是为了节省代码编写,其中可以继承一个也可继承多个。

  • 继承的操作

    class 类名(被继承的类名):

    ​ pass

    定义类的时候在类名后加括号,括号内填入需要继承的类名。

    我们将被继承的类,也就是括号内的类称之为,父类或基类或者超类。

    将继承类的类称为,子类或者派生类。平常最常称呼的就是父类子类。

    示例:

    class Fatherclass1:
        def Father1(self):
            print("this Father1号")
    
    class Fatherclass2: 
        def Father2(self):
            print("this Father2号")
            
    class Fatherclass3:
        def father3(self):
            print("my Father3号")
    
    # 括号内可以填写一个父类,也可以填写多个父类
    class Subclass(Fatherclass1, Fatherclass2, Fatherclass3):
        print("my Sub_class ")
        
    """
    目前掌握从左到右查找每个父类中的属性即可
    """
    

继承的本质

当多个类中有同样的数据或者功能,为了避免重复劳。

将多个类其中相同的数据和功能抽出创建一个新的父类,让其他需要使用它里面功能和数据的去类继承它。

使用继承,白嫖父类其中的数据和功能。

抽象:将多个类共同的数据或者功能抽取出来形成一个基类
继承:从上往下白嫖各个基类中的数据和功能
对象:数据和功能的结合体
类:多个对象相同的数据和功能的结合体
父类:多个类相同的数据和功能的结合体
综上所述,一切都是为了节省代码。

名字的查找顺序

  1. 在不继承的情况下名字的查找顺序

    先从对象自身查找,没有的话再去产生该对象的类中查找 对象>>>类

    class Student:
        school = '清华大学'
    
        def choice_course(self):
            print('正在选课')
    # 1.产生一个空对象
    stu1 = Student()  
    
    # 2.对象查找school
    print(stu1.school)  #  清华大学
    """
    自身名称空间没有,会去产生对象的类中查找  
    在创建对象的类中找到了school>>>: 清华大学
    """
    
    # 3.对象在自身的名称空间内产生了一个新的 school
    stu1.school = '北京大学' 
    
    # 4.对象查找school
    print(stu1.school)  # 北京大学
    """
    先从对象自身的名称空间查找school
    此时的对象自身的名称空间已经有了新school
    那么第一个找的是对象自身的名称空间,找到了school>>>:北京大学
    
    """
    # 5.类在查找school 找的是类中的school>>>:清华大学
    print(Student.school)  # 清华大学
    
  2. 单继承的情况下名字的查找顺序

    先从对象自身查找,然后是产生该对象的类,然后是一个个父类 对象>>>类>>>父类

    # 示例1
    class A:
      	 name = 'from A'
       	pass
    class B(A):
       	name = 'from B'
       	pass
    class C(B):
       	name = 'from C'
       	pass
    class MyClass(C):
        name = 'from MyClass'
         pass
    obj = MyClass()
    # 查找名字name
    print(obj.name)
    """
    1.先从对象自身查找,对象自身没有
    2.再去产生对象的类中查找,如果有则找到。
    3.如果没有,再去看产生对象的类中有没有继承父类,如果有则去父类中查找
    4.父类中如果有则找到,如果没有再看父类有没有继承类如果有则取其继承的类中查找
    5.依次类推知道找到这个名字
    列如:
    	对象>>>类>>>父类>>>父类的父类>>>......
    """
    
    # 示例2
    # 定义一个类A1
    class A1:
      # A1的方法1
      def func1(self):
         print('from A1 func1')
      # A1的方法2
      def func2(self):
         print('from A1 func2')
         self.func1()  # obj.func1()
        
        
    # 定义一个类MyClass,又继承了父类A1
    class MyClass(A1):
        # MyClass的方法1
        def func1(self):
           print('from MyClass func1')
    
    # 2.MyClass产生一个空对象
    obj = MyClass()
    # 对象查找func2
    obj.func2()
    """
    1.先从对象自身查找,对象自身没有
    2.再去产生对象的类 MyClass中查找,产生对象的类 MyClass中也没有
    3.再去产生对象的类 MyClass继承的父类A1中查找
    4.父类A1中有func2,执行父类A1中的func2,此时的func2中又调用了func1
    5.那么又开始从对象自身查找func1,对象自身没有
    6.再去产生对象的类 MyClass中查找,产生对象的类 MyClass中有func1,执行func1。
    
    *****
    	只要涉及到对象查找名字 几乎要回到最开始的位置依次查找
    
    """
    
    
  3. 多继承的情况下名字的查找顺序

    也可以使用类点mro()方法查看该类产生的对象名字的查找顺序

    如果涉及到对象查找名字,那么几乎都是 对象>>>类>>>父类......

    3.1非菱形继承(最后不会归总到一个我们之定义的类上)

    # 示例1
    class F():
      	 name = 'from F'
    class E():
        pass
    class D():      
       	pass
    class C(F):
       	pass
    class B(E):
       pass
    class A(D):
       pass
    
    class MyClass(A,B,C):
         pass
    obj = MyClass()
    # 查找名字name
    print(obj.name) # 'from F'
    

    深度优先(每个分支都走到低)

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

非菱形继承(最后归总到一个我们中定义的类上)

# 示例1
class G():
  	 name = 'from G'
class F(G):
  	 pass'
class E(G):
    pass
class D(G):      
   	pass
class C(F):
   	pass
class B(E):
   pass
class A(D):
   pass

class MyClass(A,B,C):
     pass
obj = MyClass()
# 查找名字name
print(obj.name) # 'from G'

广度优先(前面几个分支都不会走最后一个类,最后一个分支才会走)

经典类与新式类

  • 经典类

    不继承object或其子类的类(什么都不继承的类)

  • 新式类

    继承了object或其子类的类

  • 版本的不同

    在python3中所有的类默认都会继承object

    也就意味着python3里面只有新式类

    在python2中有经典类和新式类

    由于经典类没有核心功能所以到了python3中直接被 砍掉了

  • 示例

    # python2中的经典类和新式类
    # 经典类
    class MyClass:
        pass
    # 新式类
    class MyClass(object):
        pass
    # python3中的类默认都是新式类
    class MyClass:  # 不加括号不写object也会被默认为此操作(object)
        pass
    """
    以后我们在定义类的时候,如果没有想要继承的父类
    一般推荐一下写法
    class MyClass(object):
        pass
    其目的是为了兼容python2
    """
    

派生方法

子类中定义类与父类一摸一样的方法并且扩展了该功能>>>:派生

class Person(object):
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Teacher(Person):
    def __init__(self, name, age, gender, salary):
        # 使用super 专门用于子类调用父类的方法
        super.__init__(name,age,gender)
        # 自己在添加需要补充的数据
        self.salary = salary

"""
当一个子类继承了一个父类,子类中需要使用了父类的功能。
但又觉得父类中的功能不够全面,又在其功能上做一些扩展,这就就叫做派生

"""

posted @ 2022-07-27 22:08  瓮小辉  阅读(29)  评论(0)    收藏  举报