2018年7月29日15:49:49
今天有时间写一篇关于Python面向对象入门的文章,其实面向对象是不属于某一门编程语言的,而是一种编程思想,如果你是第一次接触面向对象,你需要弄懂下面几个问题:
- 什么是面向对象,为什么要使用面向对象?
- 什么是类,为什么要使用类?
- 类和类对象之间是什么关系呢?
- 在Python当中,类的这个数据结构整体部署是什么样子的?
当然,如果你去百度的话,网上肯定会有各种各样的文章来介绍这些东西,我也是参考了网上很多的资料,下面是一些相关的链接:
https://blog.csdn.net/qq_20641565/article/details/78541169
https://blog.csdn.net/qq_40860784/article/details/78992714
https://blog.csdn.net/Marvel__Dead/article/details/79368272
今天我想换一个角度来介绍这些东西,当你打算学习面向对象的时候,我想你肯定已经学过了变量,函数,模块,包,而今天你将学习面向对象,这个学习顺序你是否发现了什么规律,是的,如果你仔细思考的话,你会发现由变量到类,我们正在逐渐通过一种越来越强的封装方式将一些相关的事物封装在一起,大家是否还记得包的概念:
- 在Python当中,包的本质就是一个包含有__init__.py的文件夹,创建包的目的就是利用文件夹将文件模块组织起来
然后我们在回忆一下模块的概念:在Python当中,一个模块就是一个包含了一组功能的py文件。
请注意最后四个词:组织起来,一组功能,我想说的是,你之所以学习类,也是为了通过类这种数据结构将一些相关的事物封装到一起,因为无论是函数,还是模块,还是包,随着你编程的逐渐深入化,这些数据结构已经不能满足你的编程需求,你需要一种更加合理的数据将一些相关的事物封装到一起,来满足你的编程需求,其实这就是你为什么要学习类的原因,没有想象当中的复杂。
那么到底是什么面向对象呢?其实这个问题我也不知道怎么回答,这个问题就相当于:在战场上,你问军官,为什么杀人不用刀,而要用枪,那么我来告诉你:刀固然可以杀人,但是枪杀人更快,用起来更顺。
面向对象本身是一种编程思想,一两句说不清,需要你长时间的敲代码,找到你心中的那个答案。
讲了这么多,我们来一些官方的语言,类的概念:
- 对象是特征(变量)与技能(函数)的结合,类是一系列对象共有的特征与技能的结合体
- 把一类事物的静态属性和动态可以执行的操作组合在一起所得到的这个概念就是类
- 类的一个个体就是对象,对象是具体的、实实在在的事物
- 创建类的目的就是通过类这个事物将一类事物的静态属性和相关的方法封装起来,构成一个统一的整体.
我还记得我第一使用面向对象的场景,当时我心想,反正通过函数,模块也可以实现,就不用类了(因为我当时对类也不算太了解),但是由于当时做的是一个大项目,写着,写着就被迫用类了,也许就是这么简单,很多东西,当你用的时候才知道这个东西就是你所需要的。
如果你第一次接触类,你需要知道类的这个数据结构整体布局到底是什么样的?我特意截图了一下子。
接下来我们就详细的介绍一下这几个名词的具体概念:
在Python当中,类有两种属性:数据属性和函数属性
数据属性:定义在类内部的变量称为类的数据属性,是所有对象共享的,由操作系统只分配一块内存空间,大家共同使用这一块内
存空间,对同一个变量进行操作。
函数属性:定义在类内部的函数称为类的函数属性,在默认情况下是绑定给对象使用的,即obj.func() 会把obj本身当做第一个参
数传入。
注意:对于类的数据属性来说,如果类的数据属性是不可变类型,那么类对象对其只有访问权限,如果类的数据属性是可变类型,
那么类对象对其将有修改权限(不同于Java)。
在Python当中,对象有两种属性:实例属性(静态属性)和实例方法(动态属性)。
对于上面的这些介绍,我想大部分话大家都是理解的,但是对于“
对于类的数据属性来说,如果类的数据属性是不可变类型,那么类对象对其只有访问权限,如果类的数据属性是可变类型,
那么类对象对其将有修改权限(不同于Java)
”我想大家可能存有疑惑,没错,我开始学习的时候也是存有疑惑的,因为作为Java出身到的我,确实不太理解Python这套东西,为了给大家说明清楚,我们引入两个例子:
参考博客:http://www.iteedu.com/plang/python/pythonclass/var.php
示例1:
#!/usr/bin/python
# -*- coding:utf-8 -*-
class Person(object):
country = 'Chinese' #类属性(不可变类型)
person_list = [] #类属性(可变类型)
def __init__(self,name,age):
self.name = name #实例属性
self.age = age #实例属性
def tell(self):
print('%s 的年龄是:%s'%(self.name,self.age))
person1 = Person('angela',25)
person2 = Person('Jack',26)
print(person1.__dict__) #{'name': 'angela', 'age': 25}
print(person2.__dict__) #{'name': 'Jack', 'age': 26}
person1.country = '美国' #person1 临时改国籍了
print(person1.__dict__) #{'country': '美国', 'age': 25, 'name': 'angela'} ==> 注意:person1的名称空间当中多了一个属性成员.
print(Person.country) #Chinese
print(person2.__dict__) #{'age': 26, 'name': 'Jack'}
print(person2.country) #person2还是Chinese ===> 这样看还是合理的.
person1.person_list.append(person1)
print(person1.person_list) #如果类属性是可变类型,一改全改.
print(person2.person_list)
print(Person.person_list)
"""
[<__main__.Person object at 0x000000000216D278>]
[<__main__.Person object at 0x000000000216D278>]
[<__main__.Person object at 0x000000000216D278>]
"""
看到这里,我们也许或多或少的明白了为什么在Python当中针对类属性当中当中的可变类型和不可变类型会有不同的操作机制。
OK,接下来我们进行一道更有挑战性的试题,这道题我是从网上copy下来的,感觉还挺好的,如果你这道题差不多了,说明你对类属性(可变类型+不可变类型)以及实例属性的理解就差不多了。
#!/usr/bin/python
# -*- coding:utf-8 -*-
class A(object):
x = []
y = 0
def __init__(self):
pass
def add(self):
self.x.append('1')
self.y += 1 #self.y = self.y + 1(注意:前面的self.y是对象的,后面的self.y是类属性的.)
a = A()
print(a.x, a.y) #[],0
print(A.x, A.y) #[],0
a.add()
print(a.x, a.y) #['1'],1
print(A.x, A.y) #['1'],0 ====> A.y还会0
b = A()
print(b.x, b.y) #['1'],0
print(A.x, A.y) #['1'],0 ====> A.y还会0
result:
[] 0
[] 0
['1'] 1
['1'] 0
['1'] 0
['1'] 0
Process finished with exit code 0