Python 是一门完全面向对象的语言。在 Python 中,一切都是对象。从我们开始使用 Python 时,我们就已经使用了 Python 中的对象和类。
Python 程序中的每一个元素都是类的一个实例,如数字、字符串、列表、字典这些元素,都是 Python 内置类对应的一个对象,甚至于使用 def 关键字定义的一个函数都对应一个 function类。
面向对象基础
Python 使用 class 关键字声明一个类。
一个典型的 Python 类主要包含以下成员:
构造函数 (constructor)
实例属性 (Instance Attributes)
类属性 (Class Attributes)
方法 (Class Attributes)
一个类也可以没有任何成员,如下面的 Car 类就没有任何成员:class Car:
'''This is an empty Car Class'''
pass
下面的类则包含了实例属性、类属性、构造函数、方法等成员:class Car:
brand = 'BenChi'
def __init__(self):
self.price = 10000
self.chair = 7
def run(self):
print('Run 100km Per Hour....')
构造函数
在 Python 中,构造函数是实例化一个类对象的时自动被调用的函数,类似于 Java 或 C# 中的构造函数。构造函数必须使用一个特定的名称 __init__ ,并且必须有一个固定的参数 self 。
Python 类中 几乎 每一个方法都要将 self 作为第一个参数,self 是调用该方法的对象的引用。其实,第一个参数的名字是任意的,并不一定要叫 self, self 只是一种约定。
注意,注意,注意: __init__ 方法并不是 Python 类构造函数,关于 Python 类的构造函数其实有很大争议,这里主要是为了介绍面向对象的概念。
下面的例子定义了一个构造函数:class Car:
def __init__(self):
print('Call Constructor......')
car1 = Car()
car2 = Car()
Python 中构造函数( init )的作用定义了类实例的属性,并对实例属性进行复制。
实例属性
实例属性是与类实例绑定的属性,其定义在构造函数( init )中。
下面的例子定义了两个实例属性:class Car:
def __init__(self):
self.price = 100
self.chair = 7
类属性
类属性不同于实例属性,类属性的值被所有实例对象共享。类属性在类级别定义而不是定义在__init__ 方法中。类属性的访问也不同于实例属性,类属性的访问是通过类名, 也可以通过实例访问。
下面例子定义了一个类属性class Car:
brand = "benchi"
print(Car.brand)
通过类名修改类属性
通过类名修改类属性,那么该类所有的实例对象对应的类属性都会被修改, 如下:class Car:
brand = "benchi"
car1 = Car()
car2 = Car()
print('Before Change.............')
print(f'car1 brand is: {car1.brand}')
print(f'car2 brand is: {car2.brand}')
print('Change Class Attribute By [Class Name]')
Car.brand = 'Audi'
print('After Change.............')
print(f'car1 brand is: {car1.brand}')
print(f'car2 brand is: {car2.brand}')
输出:
Before Change.............
car1 brand is: benchi
car2 brand is: benchi
Change Class Attribute By [Class Name]
After Change.............
car1 brand is: Audi
car2 brand is: Audi
类方法
在一个类中,可以定义尽可能多的类方法,一般情况下,类方法的第一个参数都是 self 。
下面的类就定义了一个类方法:class Car:
brand = "benchi"
def run(self):
print('Run......')
面向对象之封装
面向对象语言,如Java、C++等,使用 public 、 protected 、 private 等关键字来控制对类资源的访问。
类的 private 成员仅能在类内部进行访问,其他任何地方都不能访问,包括其子类。
类的 protected 成员可以在类内部和其子类中访问。
类的 public 成员可以在任何地方进行访问。
Python没有使用关键字机制来限制对类成员方法和类成员属性的访问,Python规定了一种约定,在类方法或者类成员前加 _ (下划线)或者 __ (双下划线)来模拟 private 或者 public 访问修饰其的功能。
面向对象之继承
在面向对象编程中,继承是达到代码重用目的的一种方式。在继承中,子类可以使用其父类的一部分代码。
继承的基本使用
下面先创建一个父类, 代码如下:class Fish:
def __init__(self, first_name, last_name="Fish",
skeleton="bone", eyelids=False):
self.first_name = first_name
self.last_name = last_name
self.skeleton = skeleton
self.eyelids = eyelids
def swim(self):
print("The fish is swimming.")
def swim_backwards(self):
print("The fish can swim backwards.")
接下来,创建一个没有任何方法和属性的子类,代码如下:class Trout(Fish):
pass
Python类继承的语法是在定义类的时候,传入父类的名字作为参数
由于 Trout 类继承了 Fish 类, Trout 类就是 Fish 类的子类, Trout 类的对象就可以调用其父类的所有方法,代码如下:
terry = Trout("Terry")
print(terry.first_name + " " + terry.last_name)
print(terry.skeleton)
print(terry.eyelids)
terry.swim()
terry.swim_backwards()
输出:
Terry Fish
boneFalseThe fish is swimming.
The fish can swim backwards.
接下来,再创建另一个子类,该子类有自己的方法:class Clownfish(Fish):
def live_with_anemone(self):
print("The clownfish is coexisting with sea anemone.")
创建 Clownfish 的一个对象,并调用其方法:class Clownfish(Fish):
def live_with_anemone(self):
print("The clownfish is coexisting with sea anemone.")
casey = Clownfish("Casey")
print(casey.first_name + " " + casey.last_name)
casey.swim()
casey.live_with_anemone()
输出:
Casey Fish
The fish is swimming.
The clownfish is coexisting with sea anemone.
从输出结果可以看出, Clownfish 的对象 casey 可以调用其父类的 swim() 方法和 __init__() 方法,同时可以调用它自身的 live_with_anemone() 方法。