20190313-面向对象的简单理解
对象的概念
对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。 程序中所有东西都是对象。可以将对象想象成一种新类型的变量,它保存着数据, 对外提供服务,对自己的数据进行操作。 每个对象都有自己的存储空间,可以容纳其他对象。利用封装机制,可以以现有对象为基础构造出新的对象。每个对象都有一种类型。每个对象都是某个类的一个实例。
类
类:用来描述具有相同的属性和方法的对象的集合(相关数据存在一起,并且有一组操作相关数据的方法),类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。将类实例化就得到了现实世界实体的面向对象的映射——对象。
class Person():#定义Person类,()中为基类(可以有多个基类) total_count = 0 def __init__(self,name):#构造方法,初始化数据 self.name = name
#name为局部变量,self.name为实例变量,total_count为类变量 #类变量的参数即可以用类名来操作,又可以用实例来操作 def get_name(self):#实例方法 print(self.name) p1=Person("老吴") p1.get_name()
实例
根据模板创建不同的实例即为类的实例,也是对象。上述p1就是一个实例对象。
self的作用
self传递的是某个实例的地址。实例地址里面的所有变量都可以在方法中进行使用。类中方法参数包含self的方法称之为实例方法,每个实例方法只能操作本实例的实例变量;变量前面加有self.的叫做实例变量。如果不加self.的叫做局部变量。类中的实例方法中的第一个参数self,实际上就是实例所在内存的地址,通过这个地址,可以找到实例方法中需要使用的各种实例属性(数据)。
self调用过程举例:
类Person放在内存地址:xxxxyyy1
get_name():这个方法的调用要有一个self参数
实例p1放在内存地址:mmmmzzzz2
name=“老吴”
p1.get_name()的调用过程:
1)在xxxxyyy1中先把get_name()的内容找出来想去调用。
2)实例变量p1的内存地址 --->self=mmmmzzzz2
3) get_name(self=mmmmzzzz2)
4) 执行方法体:print(self.name)
5) 去mmmmzzzz2找到name的值,然后打印
6) 完成。
类里面变量
类里面定义私有变量不允许外部修改,公有变量可以通过实例.变量=xxx的格式进行赋值修改。
class Person: def __init__(self,name,age): if isinstance(age,int) and age >0: self.__age = age#私有变量不允许外部修改 else: self.__age = 0 #如果写作self.age = 0,则实例化后可以通过p1.age = xxx来修改 self.name = name def set_age(self,age): if isinstance(age,int) and age >0: self.__age = age def get_age(self): return self.__age p1=Person("wulaoshi",18) p2=Person("lilaoshi",28) #print(p1.__age)#系统报错,因为__age是私有变量,不允许外部访问 print(p1.get_age())#输出结果为100
类里面的实例方法调用
类里面的实例方法调用,使用self.方法来进行类里面的内部方法调用
#类里面的实例方法调用 class P(): def print_sth(self): print('Ppppp') def func(self): self.print_sth() #类里面的实例方法调用,使用self.方法来进行类里面的内部方法调用 a = P() a.func()
类的继承
子类可以继承所有父类的方法,并调用称之为继承
类的继承 子类可以继承所有父类的方法,并调用称之为继承 #类的继承 #父类,父类的私有属性和私有方法都不能被继承 class Person(): def __init__(self,name): self.name = name def set_name(self,name): self.name = name def get_name(self): return self.name #子类 class AsianPerson(Person): def __init__(self,name,nation): Person.__init__(self,name)#父类的初始化,通过这句话,父类所有的实例和方法都能被子类是使用 #子类想使用父类的方法、变量,则必须在子类的构造函数中来完成父类实例的构造方法的调用 self.nation = nation def set_nation(self,nation): self.nation = nation def get_nation(self): return self.nation hmaggie = AsianPerson('Hmaggie','China') print(hmaggie.get_name())#输出结果Hmaggie print(hmaggie.get_nation()) hmaggie.set_name('He-Ya-juan') print(hmaggie.get_name() #因为AsianPerson类继承了Person类里面所有的方法,所以AsianPerson的实例对象hmaggie能调用AsianPerson的父类Person的所有方法
子类调用父类的方法
子类调用父类的方法一共有三种:
super().set_name(name)
person.get_name(self)
super(asianperson,self).get_name()
如果父类中有一个方法是修改自己私有属性的,那么子类调用父类就能修改父类的私有属性
class Person(): def __init__(self,name): self.name = name def set_name(self,name): self.name = name def get_name(self): return self.name #子类 class AsianPerson(Person): def __init__(self,name,nation): Person.__init__(self,name)#父类的初始化,通过这句话,父类所有的实例和方法都能被子类是使用 #子类想使用父类的方法、变量,则必须在子类的构造函数中来完成父类实例的构造方法的调用 self.nation = nation def set_nation(self,nation): self.nation = nation def get_nation(self): return self.nation def get_name(self):#重写父类的get_name方法 return '***:'+self.name def set_name(self):#子类调用父类的方法 #三种调用父类的方法: ''' super().set_name(name) Person.get_name(self) super(AsianPerson,self).get_name() ''' super().set_name() print('ok') hmaggie = AsianPerson('Hmaggie','China') print(hmaggie.get_name()) print(hmaggie.get_nation()) hmaggie.set_name('He-Ya-juan')#输出ok print(hmaggie.get_name())
类和实例的总结
1. 可以封装数据,制定数据的存储规则,保证数据的安全
2. 类相当于模板,可以通过构造函数做初始化,快速生成实例
3. 基于类,可以进行扩展。(设计模式)
4. 内存中存储的类变量和方法,只有一份。每个类的实例,都在内存中有一个地址(类产生的实例可以有0个、1个或多个)
5. 类中定义的实例方法(方法中有self参数),可以操作每个实例中封装的变量
6. 实例变量(self.开头的)可以在不同的实例方法中被访问。实现变量都存在对应的实例所在的内存地址中。
7. __变量是私有变量,除了类中的实例方法可以访问,外部不可以直接访问和修改。