面向对象概念
和java一样,类(class)和对象是面向对象的体现,它是一种设计思想现实生活在计算机世界的映射。类的最基本作用就是封装代码,在一个类里可以定义很多个类。
1,类的定义
1 | class Student(): |
1.1 方法与函数的区别
1,实际上很多时候我们都把他们划等号,java、c#一般称为方法,c和c++一般称函数。
2,方法:趋向于面向对象的概念,python建议称方法,在模块里就建议称函数。
3,函数:面向过程的概念
当然没有必要刻意强调它们的区别
1.2 变量
1,在模块中定义的就称变量
2,在类中定义的就称为数据成员(这样以体现封装性)。
1.3 类和对象的关系和区别
类的定义:类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起。
类只是一类事物的总称,并不是一个具体的集合,具体的对象表示具体的类的一个实例,类的实例化就生成一个对象。
1.4 类的实例化
1 | student1 = Student() |
构造函数只能返回none,不能返回其他类型的值,比如字符串。
我们在实例化对象的时候要在构造函数传入定义的变量,然后赋值,在生成对象的时候传入我们要定义的实际参数的值,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
30class Student():
name = ''
age = 0
def __init__(self,name,age):
#这是构造函数
name = name
age = age
def print_file(self):
print('name:' + self.name)
print('name:' + str(self.age))
student1 = Student('石头',18)
print(student1.name)
#打印
PS G:\python> python test10.py
#但是输出却是空,为什么?再看一个小例子:
c = 50
def add(x,y):
c = x + y
print(c)
add(1,2)
print(c)
#输出结果
PS G:\python> python test11.py
3
50
这里我们在函数内部打印c的值是3,在外部打印c的值是50,在函数里面c是局部变量,不会改变全局变量的值,不过类的情况不同。下面分析一下。
1.5 类变量和实例变量
类变量时和类相关联的,实例变量是和对象相关联的,python里面是用self.变量名来保存实例变量的值。如下代码所示,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
45class Student():
name = ''
age = 0
def __init__(self,name,age):
#这是构造函数
self.name = name
self.age = age
def print_file(self):
print('name:' + self.name)
print('name:' + str(self.age))
student1 = Student('石头',18)
# student1 = Student('石敢',18)
print(student1.name,student1.age)
#运行结果
PS G:\python> python test10.py
石头 18
#再看如下代码
class Student():
#不适合定义在这里
name = 'qiyue'
age = 0
def __init__(self,name,age):
#这是构造函数
self.name = name
self.age = age
def print_file(self):
print('name:' + self.name)
print('name:' + str(self.age))
student1 = Student('石头',18)
student2 = Student('石敢',18)
print(student1.name)
print(student2.name)
print(Student.name)
#运行结果
PS G:\python> python test10.py
石头
石敢
qiyue
两个对象的name是不同的,所以打印出不同的结果,最后一行打印出qiyue,这是类变量,但是这样没有意义,名字和年龄应该定义成实例变量,而不是定义在如上代码的位置,因为类不是具体的一个对象。
下面分析一下类变量和实例变量的有关问题1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Student():
name = 'qiyue'
age = 0
def __init__(self,name,age):
name = name
age = age
student1 = Student('石头',18)
print(student1.name)
#打印
PS G:\python> python test10.py
qiyue
qiyue
如上代码所示,我们打印对象student1的name是qiyue,直接打印类的变量name值也是qiyue,后者好理解,可是我们为什么试图打印student1的name也是qiyue而不是石头呢?1
2
3def __init__(self,name,age):
name = name
age = age
我们这样写是不会给对象赋值的,应该配合self来使用。1
2
3def __init__(self,name,age):
self.name = name
self.age = age
self
如果定义的是实例方法,那我们必须在方法的参数列表第一个固定加上self,这是python的规定(实际上也可以用this,不过建议self),要显式的传入self,self就代表当前对象,不过我们调用实例方法的时候不需要传self,代码:1
2
3
4
5
6
7
8
9
10
11#定义的时候要在参数列表第一个位置加self
class Student():
name = 'qiyue'
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
#调用的时候则不需要这么做
student1 = Student('石头',18)
如果要在实例方法中和函数外访问类变量,应该用类名.变量名调用。方法一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
34class Student():
sum1 = 0
name = 'qiyue'
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
print(Student.sum1)
student1 = Student('石头',18)
print(student1.name)
print(Student.sum1)
class Student():
sum1 = 0
name = 'qiyue'
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
print(Student.sum1)
student1 = Student('石头',18)
print(student1.name)
print(Student.sum1)
#运行结果
PS G:\python> python test10.py
0
石头
0
方法二:通过self,self有一个自带的class,它就是Student类。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Student():
sum1 = 0
name = 'qiyue'
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
print(self.__class__.sum1)
student1 = Student('石头',18)
print(student1.name)
print(Student.sum1)
#打印结果
PS G:\python> python test10.py
0
石头
0
2,类方法
为什么会有类方法?它有什么作用?
1 | class Student(): |
类变量也有一个专门操作它的方法,叫类方法1
2
3@classmethod
def plus_sum(cls):
pass
这是类方法定义的规范,在方法前面添加一个装饰器@classmethod。类方法怎么调用呢?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
30class Student():
sum = 0
# name = 'qiyue'
# age = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.__class__.sum += 1
print('当前班级学生总数为:' + str(self.__class__.sum))
@classmethod
def plus_sum(cls):
cls.sum += 1
print(cls.sum)
student1=Student('小明', 18)
Student.plus_sum()
student1=Student('小强', 18)
Student.plus_sum()
student1=Student('小黄', 18)
Student.plus_sum()
#打印
PS G:\python> python test10.py
当前班级学生总数为:1
2
当前班级学生总数为:3
4
当前班级学生总数为:5
6
实例化对象的时候,对sum操作 加1,然后在类方法中又对sum进行加1操作,所以会如上代码打印。cls可以 叫别的名字吗?可以,我们换成self也同样可以。实例方法关联的是对象,类方法关联的是类。这是区别,既然可以在实例方法中操作类变量,那还要类方法做什么?因为在操作与对象无关的变量,最正确的方法还是用类方法(实例方法也可以,但是不建议)。
self和cls
self是可以代表当前对象的一个参数;cls是代表当前类的一个参数,代表当前类。
也可以用对象调用类的方法(不建议,java中就不可以这么做)。
3,静态方法
定义:1
2
3@staticmethod
def add(x,y):
print('This is a static method')
调用:1
2
3
4
5
6
7
8
9...
student1=Student('小明', 18)
student1.add(1,2)
Student.add(1,2)
...
#运行结果
PS G:\python> python test10.py
This is a static method
This is a static method
注:省略了部分代码。静态方法可以用类和对象调用。静态方法也可以访问类变量。静态方法不建议经常用。
4,成员的可见性
面向对象语言都有这个概念,java使用private、public来修饰,也叫权限修饰符。python是怎么定义一个方法的权限呢?:双下划线。
在方法前面加双下划线。如:1
2
3
4
5def __marking(self,score):
if score < 0:
return '分数不合法,请重新打分'
self.score = score
print(self.name + '同学本次考试分数为:' + str(self.score))
这里有个疑问,构造函数也是前面有双下划线为什么不是私有的?仔细看,init后面还有双下划线,在python里,函数名前后都有双下划线就不会被认为是私有函数,我们可以运行函数来证明:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20...
def marking(self,score):
if score < 0:
return '分数不合法,请重新打分'
self.score = score
print(self.name + '同学本次考试分数为:' + str(self.score))
...
student1=Student('小明', 18)
result = student1.marking(-9)
print(result)
#运行结果
PS G:\python> python test10.py
分数不合法,请重新打分
#这里运行了marking方法,我们在前面加双下划线,运行结果如下:
PS G:\python> python test10.py
Traceback (most recent call last):
File "test10.py", line 50, in <module>
result = student1.marking(-9)
AttributeError: 'Student' object has no attribute 'marking'
#果然,现在不能访问了,"no attribute 'marking'",我们再在marking后面加双下划线 "__marking__",则可以调用。当然这样不建议,因为它是python内置的定义方式。
我们可以强制访问,在调用的时候在变量前面加双下划线。如: student1.__score = 1.1
2
3
4
5
6
7
8
9student1=Student('小明', 18)
result = student1.marking(9)
student1.__score = -9
print(student1.__score)
#打印
PS G:\python> python test12.py
小明同学本次考试分数为:59
-1
{'name': '小明', 'age': 18, '_Student__score': 59, '__score': -1}
注意 _Student__score ,它就是我们定义的私有变量score,这是python私有变量的保护机制。为什么我们访问不到这个score变量,实际上就是python修改了它的名字,前面加上单下划线和类名。严格意义上python并没有私有变量。我们还是可以访问所谓的私有变量,”students._Student__score”。1
2
3
4
5
6
7
8
9
10
11student1=Student('小明', 18)
student2=Student('小兰', 18)
result = student1.marking(59)
student1.__score = -1
print(student1.__score)
print(students._Student__score)
#打印
PS G:\python> python test12.py
小明同学本次考试分数为:59
-1
0