对象独有的功能,动静态方法,面向对象三大特征,名字查找顺序,派生方法...

1.对象独有的功能

2.动静态方法

  2.1动态方法

    2.2静态方法

3.面向对象三大特征(继承(最为重要),封装,多态)

  3.1继承

    3.2继承的本质

4.名字查找顺序

   4.1不继承的情况下名字查找顺序

   4.2单继承的情况下名字的查找顺序

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

5.经典类与新式类

  5.1经典类

    5.2新式类

6.派生方法

1.对象独有的功能

  在上一章中我们初步了解了类和对象之间的关系,类是多个对象相同功能的结合体,对象是数据与功能的结合体,同时类+括号可以产生实例化对象,下面让我们进一步了解他们之间的关系

  我们先来看一段代码:

class Person:
    h_type = '人类'

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

我们先创建一个对象p1p1 = Person('jason'),此时如果我们想给这个p1加一些独有的功能该怎么加呢,有人会想到函数,但是在全局名称空间创建不久谁都可以调用了吗,在类体里面加吗?那样有这个类体创建的对象不也都可以调用吗,其实,pycharm给我们提供了一个方案,就是在类体里面创建函数,???问号三连,pycharm会将从同一个类体里面产生的对象都看成一个个独立的对象。我们来看:

class Person:
    h_type = '人类'

    def __init__(self, name):  # 让对象拥有独有的数据
        self.name = name
    # 定义在类中的函数 我们称之为方法(功能)
    def eat(self):  # 是多个对象公共的方法 也算多个对象独有的方法  对象来调用就会将对象当做第一个参数传入
        print('%s正在干饭'%self.name)
p1 = Person('jason')
p1.eat()    # jason正在干饭
p2 = Person('kevin')
p2.eat()    # kevin正在干饭

那么如何理解绑定,我们知道类体实例化函数的方法虽然是独立的,但是类体内的方法类名是否可以调用?

p1 = Person('jason')
p1.eat()
# p1 在使用句点符调用Person类体内的功能时不用传参就可以执行
Person.eat()
# 类名虽然也有句点符,但是在调用类体内功能的时候不传参数就会报错
Person.eat('我需要参数')

对于self, 就是对象在调用的时候会将对象作为第一个参数也就是self传入,而类在调用的时候有几个形参我们就要传几个实参

总结:

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

 

上述是给对象的特定方法,下面我们再深入研究类和对象的方法

2.动静态方法

  2.1动态方法

class Student:
    school = '清华大学'

    # 绑定给对象的方法
    def run(self):  # self用于接收对象
        print('老六赶紧跑!!!', self)

    @classmethod  # 绑定给类的方法
    def eat(cls):  # cls用于接收类
        print('老六你可真有才', cls)

 我们对这段代码执行下面的操作:

stu1 = Student()
stu1.run()  # 对象调用会自动将对象当做第一个参数传入    老六赶紧跑!!! <__main__.Student object at 0x00000207DE0DF2E0>
Student.run(stu1)   # 类调用需要传参数进去才能执行    老六赶紧跑!!! <__main__.Student object at 0x00000207DE0DF2E0>
# 调用绑定给类的方法
Student.eat()  # 类调用会自动将类当做第一个参数传入    老六你可真有才 <class '__main__.Student'>
stu1.eat()  # 对象调用会自动将产生该对象的类当做第一个参数传入  eat(Student)    老六你可真有才 <class '__main__.Student'>

综上得知:

  1.绑定给对象的方法,对象可以直接使用,而类要使用就要传参数进去

  2.绑定给类的方法,类可以直接调用,而对象想要调用不用传参数,但是对象调用会自动将产生该对象的类当做第一个参数传入

2.2静态方法

  静态方法很简单,可以理解为普通函数,对于类的调用,对象的调用,他需要几个参数我们都要给几个参数(参数少或者多都会报错)

class Student:
    school = '清华大学'

    @staticmethod  # 静态方法
    def sleep(a, b):  # 无论谁来调用都必须按照普普通通的函数传参方式
        print('老六快去睡觉吧')
stu1 = Student()
Student.sleep(1,2)  # 老六快去睡觉吧
stu1.sleep(1, 2)    # 老六快去睡觉吧

 

3.面向对象三大特征(继承(最为重要),封装,多态)

  3.1继承

  继承的含义:

在编程世界里继承其实就是用来描述类与类之间数据的关系

                    eg:类A继承了类B(就是A拥有了B里面的所有的数据和功能)

   继承的目的:

编程世界里继承就是为了节省代码编写

                 eg:可以继承一个类 也可以继承多个类

   继承的操作:

  class 类名(需要继承的类名):

class Father:
    money = 1000000000000
    def run(self):
        print('你有钱吗')

class Son(Father): # Sun继承了Father里面的数据和功能
    pass
# 通过Son调用Father里面的数据和功能
print(Son.money)
Son.run(1)

  ps:

    1.定义类的时候在类名后加括号
         2.括号内填写你需要继承的类名
         3.括号内可以填写多个父类 逗号隔开即可

    我们将被继承的类称之为: 父类或基类或超类
    我们将继承类的类称之为: 子类或派生类
    ps:平时最常用的就是父类和子类

3.2继承的本质

  继承的本质分为两个部分:

    抽象:将多个类共同的数据或功能抽取出来形成一个基类(可以看成大爹)
    继承:从上往下白嫖各个基类(大爹)里面的资源

4.名字查找顺序

4.1不继承的情况下名字查找顺序

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

不继承的情况下名字的查找顺序
 class Student:
    school = '清华大学'
    def choice_course(self):
        print('你喜欢上课吗')
stu1 = Student()
print(stu1.school)  # 清华大学
# 对象查找school 自身名称空间没有 所以查找的是类的

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

print(stu1.school)  # 野鸡大学
print(Student.school)   # 清华大学

所以不继承的情况下名字的查找顺序为:对象》》》类

4.2单继承的情况下名字的查找顺序

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

单继承的情况下名字的查找顺序
 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()
    # obj.name = '我很困!!!'
    print(obj.name)
	对象 >>> 类 >>> 父类...
 	class A1:
    def func1(self):
        print('from A1 func1')
    def func2(self):
        print('from A1 func2')
        self.func1()  # obj.func1()
    class MyClass(A1):
        def func1(self):
            print('from MyClass func1')
    obj = MyClass()
    obj.func2()

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

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

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

                偷个懒

      

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

主要查找顺序:

######################################################
主要涉及到对象查找名字 那么几乎都是
    对象自身   类   父类
######################################################

5.经典类与新式类

5.1经典类

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

5.2新式类
       继承了object或其子类的类

object?????啥玩意
  定义类的时候class Myclass: pass 等价于 class Myclass(object): pass


在python3中所有的类默认都会继承object,也就意味着python3里面只有新式类
python2中有经典类和新式类,由于经典类没有核心的功能 所以到了python3直接砍掉了
    
以后我们在定义类的时候  如果没有想要继承的父类 一般推荐以下写法
    class MyClass(object):
        pass
目的是为了兼容python2


以后写代码针对object无需关心 知道它的存在即可

6.派生方法

  在我的理解就是一个类产生了多个对象,然后每个子类都想在拥有自己独特的方法

派生方法的概念
 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)  # 先调用父类的方法
        super().__init__(name,age,gender)  # super专门用于子类调用父类的方法
        self.level = level  # 自己再补充一些

class Student(Person):
    pass
posted @ 2022-07-27 19:39  没错,干就完了!  阅读(59)  评论(0)    收藏  举报