宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

什么是类?

  在python中,把具有相同属性和方法的对象归为一个类(class)。类是对象的模板或蓝图,类是对象的抽象化,对象是类的实例化。类不代表具体的事物,而对象表示具体的事物。

类的创建

class Foo:
    def bar(self):
        pass

第一行定义了类名:语法是class 后面紧接着类的名字,这样来定义一个类。(Ps:类的名字,首字母,有一个不可文的规定,最好是大写,这样需要在代码中识别区分每个类。)
第二行开始是类的方法,大家看到了,和函数非常相似,但是与普通函数不同的是,它的内部有一个“self”,参数,它的作用是对于对象自身的引用。

类的特点

类对象是多态的:也就是多种形态,这意味着我们可以对不同的类对象使用同样的操作方法,而不需要额外写代码。
类的封装:封装之后,可以直接调用类的对象,来操作内部的一些类方法,不需要让使用者看到代码工作的细节。
类的继承:类可以从其它类或者元类中继承它们的方法,直接使用。

1. 类的封装

  对象里封装的是一些属性,而对象的方法封装在原类里,因此,当需要在其他脚本或模块中,利用其他脚本或模块的对象时,需要先导入原模块或者类。比如我在脚本(1)中定义了A对象,并且通过pickle的方式存储到文件中,当在脚本(2)需要通过pickle载入文件时,需要先import 脚本1中的类,否则会提示找不到原类。

  类的封装可以封装类的属性和类的方法,也可以在对象中封装对象。比如:

class Foo:
    def __init__(self, name, age): #将name和age属性,封装到类中
        self.name = name
        self.age = age

    def speak(self, word): # 将speak方法封装到类中
        print("%s say %s" % (self.name, word))

F = Foo(name='诸葛亮', age=18)
F.speak('hello')
out: 诸葛亮 say hello

上边的__init__和self是什么鬼?

  self是Python的类在实例化的时候,自动传值的东西,代表对象本身。多个对象,则self会在不同对象调用的时候,代表不同对象。

  而__init__是类的构造方法,在类进行实例化的时候会自动执行。

2. 类的继承

  类的继承就是可以从其他类中继承其他类的方法来使用。

class Human:
    def  __init__(self):
        self.sex = ['man', 'woman']

    def eat(self):
        print("Human can eat, for example: %s" % self.name)

class Man(Human):
    def __init__(self, name, age): #将name和age属性,封装到类中
        self.name = name
        self.age = age

    def speak(self, word): # 将speak方法封装到类中
        print("%s say %s" % (self.name, word))

F = Man(name='诸葛亮', age=18)
F.eat() # 调用了父类的eat方法
out:
Human can eat, for example: 诸葛亮

  其中Man类是Human类的子类,也叫做派生类。

  Human是Man类的父类,也叫做基类。

上边的代码实现了简单的继承,且继承关系简单,只有一个父类, 因此属于单继承。另外也有多继承,即从多个父类继承。

  在使用多继承的时候, 子类调用父类的方法,如果多个父类无交集,会采用从下到上,从左到右的原则进行匹配。如果多个父类有交集,则采用从下到上, 直至交集前,然后从左到右进行匹配。这种方法叫做“广度优先”。

  这里的从左到右是指,继承的先后, 比如Foo(Left, Right),那么Left类就是左,优先进行向上查找。

     从下到上是指,从Foo类开始查找,然后查找Left类,然后查找Left类的父类直至交集前的最后一层父类。图示如下:

             Python菜鸟之路:Python基础-类(1)——概念-冯金伟博客园

3. 类的多态

   在Python用谈多态没有多大意义,多态的概念是应用于Java和C#这一类强类型语言中。在Java中,在类定义的时候,已经定义好了参数输入的类型,这与Python中是不同的。但是为了在Java中,支持Python中这样多种形态的参数输入形式,就有了多态的用法。它的实现是基于继承来实现的,用Python伪代码来表示如下:

class A:
    pass

class B(A):
    pass

class C(A):
    pass


# 要求arg必须是A类型
def func(arg):
      pass

#使用继承的话,就可以按照如下的方式使用
obj1 = B()
obj2 = C()

# 这样的话,obj1和obj2就可以作为多态参数输入
func(obj1)
func(obj2)

多态python版

4. Python2 类中的多继承

  在上边已经介绍了Python3 中类的多继承为“广度优先”,那么在Python2中呢?

  对于经典类,Python2中的继承为“深度优先”。

  对于新式类,Python2中的继承为“广度优先”。

  上边的两句话怎么理解呢?那么什么是新式类,什么是经典类?

       其实很简单,新式类和经典类的区别,在书写的时候就能看出来,经典类:class A:….    ; 新式类: class A(object)。可以看出,二者区别就是创建的时候有没有继承自object.

  如何用代码测试,请看如下代码

 1 class A:
 2     def f1(self):
 3         print('A')
 4 
 5 class B(A):
 6     def f1(self):
 7         print('B')
 8 
 9 class C(A):
10     def f1(self):
11         print('C')
12 class D(B):
13     def f1(self):
14         print('D')
15 
16 class E(C):
17     def f1(self):
18         print('E')
19 
20 class F(D, E):
21     def f1(self):
22         print('F')

  上边我定义了一种继承关系。测试步骤如下:

1. 创建F对象

obj = F()

2. 循序渐进调用对象方法

obj.f1()

  每次调用obj.f1()都会打印出当前调用的是那个类中的f1方法。接下来修改对应类中的f1函数名,让f1方法在当前类中无法找到,这样就会触发子类去父类中去查找f1方法。多次尝试之后,可以得出如下的继承顺序图,从而验证了,经典类的多继承关系是深度优先!图示如下:

            Python菜鸟之路:Python基础-类(1)——概念-冯金伟博客园

  Python2 关于新式类的多继承关系,测试方法同上,最终结果表明:新式类的继承是“广度优先”。图示如下:

             Python菜鸟之路:Python基础-类(1)——概念-冯金伟博客园