Python的面向对象编程

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

参考连接

廖雪峰Python面向对象编程教程

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。

而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

对象:类与实例

python中,一切皆对象,所以类和实例,本质也还是对象,被称为类对象和实例对象。

类对象(class)是用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。

实例对象(object)是指通过类定义的数据结构实例。python中的对象都会有三个特征: - 身份,即是存储地址,可以通过id()函数来查询。 - 类型,即对象所属的类型,可以用type()函数来查询。 - 值,都会有各自的数据,由魔法函数 __str__ 决定,默认会输出引用的对象

反过来说,实例就是对象在内存中开辟了空间。

父母口中的女朋友(对象),怀里搂着的她(实例)。

Python类方法、类属性、静态方法

实例方法 类方法 静态方法
定义 第一个参数必须是实例对象,该参数名一般约定为self,通过它来传递实例的属性和方法 使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为 cls,通过它来传递类的属性和方法 使用装饰器@staticmethod。参数随意,没有 selfcls 参数,但是方法体中不能使用类或实例的任何属性和方法
调用 只能由实例对象调用 实例对象和类对象都可以调用 实例对象和类对象都可以调用
属性及方法传递 (也可以传类的属性和方法) (不能传实例的属性和方法)

代码演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Province:
memo = 'One of China\'s 23 provinces' #静态字段

def __init__(self, name, capital, leadership):
self.Name = name #动态字段
self.Capital = capital #动态字段
self.Leadership = leadership #动态字段

# 这是实例方法
def sports(self): # 定义一个实例方法,类不能访问动态方法 self是实例本身
print(self.Name + 'The sports meeting')

# 定义类方法
@classmethod
def build(cls): # cls是类本身
p = cls('SiChuan', 'Chengdu', 'Pengqinghua')
print('cls:', cls)
return p

# 定义静态方法,实现类可以访问这个方法
@staticmethod #第一步、加一个自带的装饰器
def Foo(): #第二步,把shelf去掉
print('Anti-corruption activities')


# Test
>>> # 常用方法实例化两个对象,对象名分别是:hb、sd
>>> hb = Province('hebei','shjiazhuang','liyang')
>>> sd = Province('shandong','jinan','angshenghui')
>>> # 调用类方法实例化一个对象,对象名为:sc
>>> sc = Province.build()
cls: <class '__main__.Province'>
>>> # 对象访问实例方法(动态方法)
>>> hb.sports()
hebeiThe sports meeting
>>> sd.sports()
shandongThe sports meeting
>>> sc.sports()
SiChuanThe sports meeting
>>> # 注意:类不能访问实例方法(动态方法)
>>> Province.sports()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sports() missing 1 required positional argument: 'self'
>>> #通过类名访问静态方法
>>> Province.Foo()
Anti-corruption activities
>>> #那么,对象是否能够访问静态方法呢?答案是可以的
>>> hb.Foo()
Anti-corruption activities

参考链接

菜鸟和大白谁厉害 - python中:类方法、静态方法、动态方法的理解

补充讨论:Selfcls 的 区别

从上面可以看出 - self总是指调用时的实例对象本身。 - cls总是指向类对象本身。

关于self还有其他要点 - self在定义时需要定义,但是在调用时会自动传入。 - self的名字并不是规定死的,但是最好还是按照约定是用self

self名称不是必须的,在python中self不是关键词,你可以定义成a或b或其它名字都可以,但是约定成俗(为了和其他编程语言统一,减少理解难度),不要搞另类,大家会不明白的。

下例中将self改为myname一样没有错误:

1
2
3
4
5
6
7
class Person:
def _init_(myname,name):
myname.name=name
def sayhello(myname):
print 'My name is:',myname.name
p=Person('Bill')
print p

self指的是实例对象本身(注意:不是类本身,cls指向类对象本身)。

1
2
3
4
5
6
7
class Person:
def _init_(self,name):
self.name=name
def sayhello(self):
print 'My name is:',self.name
p=Person('Bill')
print p

在上述例子中,self指向Person的实例p。 为什么不是指向类本身呢,如下例子:

1
2
3
4
5
6
7
8
class Person:
def _init_(self,name):
self.name=name
def sayhello(self):
print 'My name is:',self.name
p1 = Person('Bill')
p2 = Person('Apple')
print(p1)

如果self指向类本身,那么当有多个实例对象时,self指向哪一个呢?

转载链接

Python类中的self到底是干啥的

访问限制

继承和多态

抽象类和接口类

获取对象信息

实例属性和类属性

抽象类和接口类

使用__slots__

使用@property

多重继承

定制类

使用枚举类

使用元类