python是一种面向对象的语言,具体表现为:封装、继承和多态。其中最重要,也是将面向对象的语言与其他语言区别开来的,就是多态。
多态是指,对一个变量进行操作时,我们不需要关心它是什么对象。比如,将a和b相加,ab可以是int,也可以是string,还可以是list;再比如,repr()函数,将对象打印出来,也可以不考虑函数参数的类型。封装与多态不同,多态让你无需知道对象所属的类(对象的类型)就能调用其方法,而封装让你无需知道对象的构造就能使用它。继承是避免重写方法和属性的很好的方法,会在后面详细说明,这里不赘述了。
class 类
有一句话很重要:类定义就是要执行的一个代码段
在class语句中定义的代码都是在一个特殊的命名空间(类的命名空间)内执行的,而类的所有成员都可访问这个命名空间。
在python中,约定使用单数及首字母大写来标记一个类。类由属性和方法组成,子类继承超类的所有属性和方法,还可以对方法和属性进行重写,扩展超类不存在的类和属性。下面定义一个类:
>>> class Myclass:
m = 0
def method(self):
print("This is my first class")
这里方法内部的self是需要我们输入的,指向这个类。我们还定义了一个类级变量m,每个新创建的类都可以对它进行操作,我们可以将其用于类的计数。
类的私有
python没有为私有属性提供支持,不过我们依然可以在属性或方法名前加两个下划线使得该属性或方法为类私有。
>>>class Myclass:
def __private_method(self):
print("This is my private")
def method(self):
print("This is not private")
self.__private_method()
当从外部试图访问私有方法时,会报错。而如果不想被从外部访问,又不想显示报错,可以加一个下划线,这是一种约定,当别人看到你的标记时,会知道这是不希望从外部访问的。
继承
>>>class A:
def f1(self):
print("This is A")
>>>class B(A)
def f2(self):
f1()
这里创建了A和B两个类,并且A是B的超类,B是A的子类,继承了A的f1()方法。
括号里可以写多个类,此时为多重继承,如果括号里的类有相同的方法,写在前面的类会覆盖后面的方法。多重继承要慎用。
抽象类
抽象类是不能实例化的类,定义了一组类需要实现的功能。python中抽象类需要用到abc模块。
>>> from abc import ABC, abstractmethod
>>> class A(ABC):
@abstractmethod
def walk(self):
pass
>>> class B(A):
def walk(self):
print("We are walking")
@abstractmethod是装饰器,用来标记需要被实例化的方法。在B中,将walk()方法进行了重写,因此B可以用来创建实例,A不可以。
构造函数
当创建一个类的时候,通常我们会写一个构造函数来初始化类。构造函数与其他函数不同,它将在创建这个类的实例的时候自动调用,而不需要显式的调用它。
构造函数命名为init.下面就是一个构造函数的例子。
>>>class MyClass:
def __init__(self):
self.count = 0
>>>c = MyClass()
>>>c.count
0
当一个类A继承另一个类B时,如果在A中重写了构造函数,那么在创建A的实例时,可能会出现问题。因此,在调用类A的构造函数前,应该先调用其超类B的构造函数。具体做法为:使用super函数。
>>>class B:
def __init__(self):
self.count = 0
>>>class A(B):
def __init__(self):
super().__init__()
self.size = 0
>>>a = A()
>>>a.count
0
>>>a.size
0
这里,super()函数返回类A的超类。当有多个超类时,super函数只调用一次。关于super函数,可以探究的内容还有很多,这里先不细讲了。
下面为一些常用函数及语句:
>>> isinstance(s, A) # 判断s是不是A类的实例
>>> A.__bases__ # 查看class A的超类
>>> issubclass(B, A) # 判断B是不是A的子类
>>> s.__dict__ # 查看属性值
>>> s.__class__ # 查看s属于哪一类
>>> hasattr(s, 'f1') # 查看s是否具有f1属性(或方法)
>>> getattr(s, 'f1', None) # 返回s的f1属性(或方法),如果没有,返回默认值(这里是None)
>>> setattr(s, 'length', 5) # 将s的属性length设为5
>>> A.register(B) # 将B注册为A,使得isinstance可以返回true