面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”!!!
1.如何创建类和实例
以Student类为例,在Python中,定义类如下:
class Student():
pass
上面就定义好了一个类,接下来就可以根据Student类创建一个实例,创建实例是通过类名+()实现的
a=Student()
!!!首先要搞清楚一个问题就是:a=Student() 和 a=Student的区别。
>>>a=Student()
a
<__main__.Student object at 0x1068f0c10>
>>>a=Student
a
<class '__main__.Student'>
从上面的输出可以看出:
- a=Stuent():有地址,说明他是一个实体,比如 int a 中的 a 一样
- a=Student:没有地址,这说明他就是一个类名, 等价于上一句中 int a 中的 int
2.self到底指的是什么?
举个例子来说明:
class Student():
def test_1(self,one):
print(one)
>>>a=Student() #创建一个实例a
>>>Student.test_1(a,'hi') #self就是实例a!
hi
>>>a.test_1('hi')
hi
结论:
- Student.test_1(a,'hi')和a.test_1('hi')的输出结果相同
- self指的是类的实例对象本身 ,而不是类本身。也就是说:self就是实例 a 自己!就是你创建的那个实例名字!就是那个上面那个a!(破音ing)
- self ,也可以用别的单词来代替。不过大家都约定俗称用self。
- 类中的方法第一个参数是 self 的才可以被实例调用,实例对这个参数拥有所有权,即实例中所有的方法都可以使用实例的参数。
3.参数前面的self
在类的代码编写中,我们常常会遇到类似以下的代码:
x=1
class Plus():
def one(self):
self.x=10
def add(self):
y=5+x
print(y)
结果:
>>>a=Plus()
>>>a.add()
6
为什么结果是6而不是15呢?
还是那个原因:self是指代的什么?
self指代的是创建的实例a!add() 方法中的 x 前面没有加 self ,所以他调用的不是实例自身的参数
所以,带self的参数才可以被实例调用,不带self的,跟实例无关。
如果要使用self里面的参数:
class Plus():
def one(self):
self.x=10
def add(self):
y=5+self.x #注意这句
print(y)
结果:
>>>a=Plus()#实例化
>>>a.one()#使用self.x值
>>>a.add()#使用add方法
15
4.应用
一般来说我们创建类和实例的时候会使用__init__
方法,__init__()
方法的作用是初始化一个类的实例。
在创建实例的时候,就把name
,score
等属性绑上去:
class Student():
def __init__(self, name, score):
self.name = name
self.score = score
注意到__init__
方法的第一个参数永远是self
,表示创建的实例本身。
有了__init__
方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__
方法匹配的参数,但self
不需要传,Python解释器自己会把实例变量传进去:
创建实例:
bart=student('lisa',99)
查看创建后实例的参数。
>>>bart.name
'lisa'
>>>bart.score
99
补充知识:数据封装
面向对象封装的另一个重要特点就是数据封装,在上面的Student
类中,每个实例就拥有各自的name
和score
这些数据,我们可以通过函数来访问这些数据。但是这样从外部访问数据比较麻烦,而数据封装是直接在Student
类的内部定义访问数据的函数。这些封装数据的函数是和Student
类本身是关联起来的,我们称之为类的方法:
# -*- coding: utf-8 -*-
class Student():
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
#创建一个实例
person=Student('jack',100)
person.print_score()
jack: 100
注意:要定义一个方法,除了第一个参数是self
外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self
不用传递,其他参数正常传入。