面向对象编程是Python中的核心之一,面向对象的核心并不是概念,语法,使用有多么复杂,而是一种编程思想,并不是掌握了类创建与使用就真正掌握了面向对象编程,这需要在不断工作与练习中逐步提升;抛去代码,我们先来看现实世界的基本概念:

类:

我们最先想到的就是分类:人,动物,植物...这些都是自然界的大类;
Python面向对象编程基础
每个类别都有自己的特征与行为,而类就是描述这些具有相同属性与方法的对象的集合。
通过一个图来全面了解面向对象基本概念:
Python面向对象编程基础

属性:

类具有的特征,对于人类来说,身高、体重、性别等是基本属性;

方法:

类具有的功能,对于人来来说:吃饭、睡觉、工作等是通用方法;

实例:

类对应的一个具体对象,比如梅西,詹姆斯都是实际存在的人;
每个实例都有自己实际属性与方法,比如詹姆斯的姓名,体重等;

方法:

对象行为的描述,对于人类来说,吃饭,睡觉,工作都是方法;

还有一些其他基本概念,我们通过Python来实际讲解。

1:类基本语法

1.1:定义类

先来看基本语法:

class 类名:
    pass
#例如:
class Person:
    pass

1>class 为关键字;
2>Person为类名称;

人类有一些共同特征与方法,我们如何在类中添加?

1.2:添类属性

人类中有公共属性,例如:居住在地球,氧气和水是必需品;我们可以将其添加到类中:

class Person:
    #居住星球
    start = 'Earth'
    #必须品:水,实物,氧气
    needlist = ['water', 'food','oxygen']

我们可以直接访问这些属性:

print(Person.star)
print(Person.needlist)

输出结果:

print(Person.star)
print(Person.needlist)

人类有一些共同方法,例如:吃饭,睡觉,工作等,如何添加到类中?

添加方法:

python中类方法分为实例方法,类方法,静态方法,其他语言中也有这些概念,可能语法不同,但是基本概念类似,我们先来看实例方法,基本语法如下:

class 类名:
    def func_name(self, *args, **kwargs):
        pass

1>类中添加实例方法,与定义函数类似,def关键字+方法名+参数;
2>实例方法的第一个参数必须是self,这是基本语法;
3>实例方法不能直接调用,只有具体对象才能调用;

添加人类方法:sleep,eat,work,say;代码实现如下:

class Person:
    #居住星球
    star = 'Earth'
    #必须品:水,实物,氧气
    needlist = ['water', 'food','oxygen']
    #第一个参数:self
    def eat(self, foodlist):
        pass
    def sleep(self):
        pass
    def work(self, tasklist):
        pass
    def say(self, what):
        pass

后面实际工作与学习中,如果我们对类掌握十分熟悉,可以先把属性与接口定义出来,然后逐步完善每一个方法就可以,为了方便后面观察调用过程,我们给每个方法加上输出信息:

class Person:
    #居住星球
    star = 'Earth'
    #必须品:水,实物,氧气
    needlist = ['water', 'food','oxygen']
    #第一个参数:self
    def eat(self, foodlist):
        print('I eat:',foodlist)
    def sleep(self):
        print('I am sleep now')
    def work(self, tasklist):
        print('my work is:', tasklist)
    def say(self, what):
        print('I say:', what)

类定义好了,我们如何来使用呢,来创建具体人的对象,实例化:

实例化

创建一个对象,对于刚才例子我们可以使用下面方式:

p1 = Person()
p2 = Person()

p2与p2就是Person类对应的两个对象,也成为实例,如何调用eat, sleep等方法?
使用实例p1,p2还是Person?当有疑问时,我们可以通过实际操作验证:

p1.sleep()
Person.sleep()

输出结果:

I am sleep now
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-3a15402f300a> in <module>()
      1 p1.sleep()
----> 2 Person.sleep()

TypeError: sleep() missing 1 required positional argument: 'self'

第一条语句正常输出,第二条是错误的,因为需要参数self;
这里我们有必要把这个搞清楚:

1>Person类中的方法都是实例方法,他的第一个参数必须是self,那么self究竟是谁?
2>如果是实例直接调用,那么self,就是实例自己,比如,p1,p2;
3>类不能直接调用实例方法,因为没有与实例进行绑定,但是可以换一种方式调用;

下面我们来验证self究竟是谁,对代码进行修改:

#定义最简Person类
class Person:
    def whoami(self):
        print('I am 0x%x'%id(self))
#创建对象
p = Person()
#id函数:显示对象内存地址
print('p id:0x%x'%id(p))
#对象调用实例方法
p.whoami()
#不推荐使用,只是用来理解实例方法,
#实例方法第一参数必须是类的一个实例
Person.whoami(p)

输出结果( 输出地址可能不同):

p id:0x7f99c06d4fd0
I am 0x7f99c06d4fd0
I am 0x7f99c06d4fd0

通过这里例子,希望对大家理解实例方法有帮助。

重要的__init__方法

定义人类了,但人有名称,年龄等自己特征,如何在实例化时候指定这些属性,这里我们需要使用__init__方法,我们先来添加一个__init__方法,看一下调用过程。

#添加__init__方法
class Person:
    def __init__(self, name):
        print('call init name:', name)
#实例化时,添加名称
p1 = Person('sun')
p2 = Person('li')

输出结果为:

call init name: sun
call init name: li

我们并没有显示调用__init__方法,这是怎么回事?
实例化过程会默认调用__init__方法,调用__init__时,实例已经创建出来,这个方法的参数对应实例化时传递参数,目的:初始化对象的属性。比如名称,如何添加实例属性?

类属性与实例属性

首先来看类属性,我们人类都属于地球,所以我们添加一个属性:

class Person:
    #居住星球
    star = 'Earth'
    name = 'unknow'
p1 = Person()
#访问star与name
print(p1.star, p1.name)

输出结果:

Earth unknow

这里我们访问p1的star与name其实访问的是类属性。

添加实例属性:

#既简单又粗暴
p1.name = 'sun'
print(p1.star, p1.name)

输出结果:

Earth sun

思考问题:这时候Person类中的name是什么?做实验验证:

print('p1.name:',p1.name)
print('Person.name:',Person.name)

输出结果:

p1.name: sun
Person.name: unknow

分析下上面步骤:

1>p1.name=sun,修改了什么?它只是对p1增加name属性,值为sun,对其他对象与Person类没有任何影响;
2>p1与Person中有了name属性,p1访问时,选择哪个?如果实例中有name属性,使用实例中属性,如果没有,去类中查找,若类中不存在报异常。

下面我们在__init__方法中直接添加实力属性,实例化时直接添加名称与年龄:

class Person:
    name = 'unknow'
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def selfintroduction(self):
        print('my name is %s, I am %d years old.'%(self.name, self.age))
p1 = Person('sun', 10)
p1.selfintroduction()

输出结果:

my name is sun, I am 10 years old.

我们有个问题,实例中的name与age被放到哪里,通过__dict__看下:

print('Person:',Person.__dict__)
print('p1:',p1.__dict__)

输出结果:

Person: {'__module__': '__main__', 'name': 'unknow', '__init__': <function Person.__init__ at 0x7f99c0748d90>, 'selfintroduction': <function Person.selfintroduction at 0x7f99c0748bf8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
p1: {'name': 'sun', 'age': 10}

通过输出信息,我们可以看到这些值存放方式,可以通过这种方式直接赋予实例新的属性,但是我们不推荐这种方式。

总结

这节我们主要内容:

1>面向对象基本概念:类,对象,属性,方法;
2>Python中类定义及实例化过程;
3>__init__方法及属性查找过程;

到这里我们对类有了基本了解,后面内容中我来介绍类的具体使用及高级使用方式。