一、面向对象编程概述
1、面向对象编程(OOP)
面向对象:以具体的事物(对象)为单位,考虑它的属性(特征)及动作(行为),关注整体。java、c#也是面向对象编程。
-
例子解读(把大象装进冰箱):为了把大象装进冰箱,需要做三个动作(行为)。每个动作有一个执行者,它就是对象,这里对象是冰箱。
- 冰箱,你给我把门打开(冰箱.开门())
- 冰箱,你给我把大象装进去(冰箱.装大象())
- 冰箱,你给我把门关上(冰箱.关门())
依次做这些动作,就能把大象装进冰箱。
-
三大特征
(1)封装(信息隐蔽技术):类的封装、函数封装,方便调用。
#创建一个list1列表对象,我们不需知道列表对象里方法的具体实现过程,封装好了,用方法名直接调用即可 >>>list1 = [1,5,2,6] >>>list1.append(10) >>>list1 [1,5,2,6,10] >>>list1.sort() [1,2,5,6,10]
(2)继承:子类继承父类的方法和属性
#创建一个Mylist类,继承list类的属性和方法 class Mylist(list): pass
>>>list2 = Mylist() >>>list2.append(4) >>>list2.append(5) >>>list2.append(6) >>>list2 [4,5,6]
类名后面紧接着是(object),表示该类是从哪个类继承下来的。通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
(3)多态:不同对象对同一方法响应不同的行动,而无需明确知道这个对象是什么。即一个方法,多种形态,就是多态。
class Person(Object): def func(self): print('我是人!') class Girl(Person): def func(self): print('我是妹子!') class Boy(Person): def func(self): print('我是汉子!') def func1(x): #涉及知识点:静态/动态类型语言,file-like object,“鸭子类型”(duck typing) x.func()
>>>a = Person() >>>b = Girl() >>>c = Boy() >>>a.func1() 我是人! >>>b.func1() 我是妹子! >>>c.func1() 我是汉子!
2、面向过程编程
面向过程:以一个具体的流程为单位,考虑它的实现方法,关心的是功能的实现(耦合性比较强)。C语言是面向过程编程。
-
例子解读(把大象装进冰箱):为了把大象装进冰箱,需要3个过程。
- 把冰箱门打开(得到打开门的冰箱)
- 把大象装进去(打开门后,得到里面装着大象的冰箱)
- 把冰箱门关上(打开门、装好大象后,获得关好门的冰箱)
每个过程有一个阶段性的目标,依次完成这些过程,就能把大象装进冰箱。
3、类和对象
类是对一组具有相同特性(属性)和相同行为(方法)的事物的概括,是抽象的模板;对象是客观世界实际存在的事物都是一个对象,即“万物万事皆对象”。对象=属性+方法
-
类是对象的模板,对象是类的实例
#定义一个人类Person,类名首字母要大写 class Person: def __init__(self,name,sex,age): self.name=name #name,sex,age是类的属性 self.sex=sex self.age=age #定义类的方法 def introduce(self): print('大家好,我叫%s,%s,今年%s岁'%(self.name,self.sex,self.age)) def eat(self): print('%s:好饿了,想吃大餐,毕竟吃饱了,才有力气减肥,嘻嘻'%self.name) def run(self): print('%s:运动让人快乐,跑步走起!'%self.name) def sleep(self): print('%s:不嗨了,早睡早起身体棒!'%self.name) #实例化,创建一个对象 >>>xiao_ming = Person('李小明','男','24') #调用Person类的方法 >>>xiao_ming.introduce() 大家好,我叫李小明,男,24岁 >>>xiao_ming.eat() 李小明:好饿了,想吃大餐,毕竟吃饱了,才有力气减肥,嘻嘻
-
拓展
1、什么是类、类对象、实例对象?
#这是一个类,定义完之后也是一个类对象 class C: count=0 ----------------------------------------- >>>a=C() #a、b、c是实例对象 >>>b=C() >>>c=C() >>>a.count 0 >>>b.count 0 >>>c.count 0 --------------------------------------- >>>c.count+=10 #实例对象覆盖了类对象里的属性 >>>c.count 10 >>>a.count 0 >>>b.count 0 --------------------------------------- >>>C.count+=100 >>>C.count 100 >>>a.count 100 >>>b.count 100 >>>c.count 10
graph TB task1("类定义 C")-->task2("类对象 C") task2-->task3("实例对象 a") task2-->task4("实例对象 b") task2-->task5("实例对象 c")
二、self是什么
类的定义里,self会出现在函数的第一个参数里(python的默认要求,必填参数,这是与普通函数的一个区别),通过哪个对象调用的方法,则self就是哪个对象
-
例子解读:(还是用上述Person类)
#实例化,创建xiao_ming对象 >>>xiao_ming = Person('李小明','男','24') #通过xiao_ming这个对象来调用introduce方法 >>>xiao_ming.introduce() 大家好,我叫李小明,男,今年24岁 #实例化,创建zhangli对象 >>>zhangli = Person('张丽','女','18') #通过zhangli这个对象来调用introduce方法 >>>zhangli.introduce() 大家好,我叫张丽,女,今年18岁
def introduce(self):
print('大家好,我叫%s,%s,今年%s岁'%(self.name,self.sex,self.age))
当对象xiao_ming调用introduce()方法时,self会调用xiao_ming的name,sex,age属性作为参数输入,然后print对应格式输出自我介绍;而zhangli这个对象调用introduce()时,则传入的是zhangli的name,sex,age。
三、访问限制:公有与私有
-
C++中,用public和private标识公有变量与私有变量,而在python中,默认情况下,对象的属性、方法都为公有的,用
.
点操作符来访问class Car: name = '本田' >>>c1 = Car() >>>c1.name #用.点操作符来访问 '本田' >>>c1.name = '丰田' #外部可自由修改c1实例的name属性 >>>c1.name '丰田'
-
若要实现类似于私有变量的特征,python内部采用了一种叫做name mangling名字改编的技术。在python中定义私有变量,只需在变量名或函数名前加上两个下划线"__",则该函数或变量就会变为私有,只有内部可以访问,外部不能访问。
class Car: __name = '本田' #定义成私有变量 >>>c1 = Car() >>>c1.name #直接用点操作符访问,会报错,属于外部调用 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Car' object has no attribute 'name' >>>c1.__name #也会报错 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Car' object has no attribute '__name'
在外部,私有变量”被隐藏“起来了,不能访问。理论上,若要访问私有变量,可通过在类中定义方法getname,内部调用来访问:
class Car: __name = '本田' def getname(self): return self.__name >>>c2 = Car() >>>c2.__name #仍会报错 >>>c2.getname() #成功运行,此时的getname()是在内部调用name属性 '本田' #注意一下下面这种错误的修改私有变量方式 >>>c2.__name = '丰田' #表面上看,外部代码“成功”地修改了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量! >>>c2.__name '丰田' >>>c2.getname()#返回class内部self.__name '本田'
虽然上述代码成功运行,而实际上,私有变量只是名字重整,被python改了名字,变为了类名_变量名而已。其实python是伪私有机制,python的类是无权限控制的,变量可被外部调用。
>>>c2._Car__name #还是用.操作符,对象._类名__变量名即可 '本田'
-
注意:
1、不同版本的Python解释器可能会把
__name
改成不同的变量名,不一定是_Car__name
!2、在Python中,变量名类似
__xxx__
的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量(魔法方法),特殊变量是可以直接访问的,不是private变量。所以,不能用__name__
、__score__
这样的变量名来定义私有变量。