面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
class类
类是对拥有相同属性的对象的抽象。
object对象
对象是通过对类的实例化得到的。一个类可以实例化很多对象。类也必须在实例化之后才能调用。
封装
在类中对数据的赋值、内部调用对外部是封闭的,这使类变成了一个胶囊或者容器,里面包含着类的数据和方法。
使外部程序不需要关注对象内部的构造,只需要通过类的对象调用对外提供的接口进行直接访问即可。
继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
多态
简单点说是一个接口,多种实现,指的是一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类方法做了不同的实现,这就是同一种事物表现出的多种形态。
定义类和对象
class Dog(object): #定义一个类 object表示从哪个类开始继承 def sayhi(self): #类的方法 self 方法自带的一个参数 print('hello,I am a dog.') d = Dog() #实例化这个类 d保存的是类的对象 print(d) #<__main__.Dog object at 0x0000000001089860> 对象的内存地址 d.sayhi() # hello,I am a dog. 调用类的方法
如果要给类传一个参数进去,怎么做呢?
实例化传参
首先在 "class Dog(object)" 括号里面是不能传参数的,类对参数的接收可以使用构造函数,这个构造函数的作用就是在类初始化的时候做的一些操作,可以定义类的属性、方法等。也可以接收参数。
class Dog(object): def __init__(self,name): #定义构造函数,添加一个name的形参 self.name = name #定义一个属性name,并且把形参的name的值传给这个属性 print(self.name) #二哈 说明类在实例化的时候执行了__init__这个方法 def sayhi(self): print('hello,I am a dog.') d = Dog('二哈') #实例化的时候传一个参数给这个类
属性的调用
class Dog(object): def __init__(self,name): self.name = name def sayhi(self): print('hello,I am a dog.',self.name) #这里的self.name 调用的是init里面的 self.name #这里不能直接写name 因为一个函数的局部变量在另外一个函数内部是识别不到的 d = Dog('二哈') d.sayhi() #hello,I am a dog. 二哈
self的意义
那么这两个函数的self参数做什么的?为什么__init__()函数里面定义的属性,在别的函数里面可以访问到?
先看下执行过程:
1 首先类实例化之后称作类的对象,也叫做类的实例。那么d,d2也叫做类的实例。
2 在实例化的时候只传递一个参数给这个类,但是__init__()这个函数有两个参数,self实际上接收的是这个类的实例,也就是d。
3 在初始化的时候定义了一个属性 NAME接收了形参的值并且把NAME绑定到了self上。
4 在调用sayhi()方法的时候是隐式的把d这个实例也传了过去,最终调用self.NAME的时候 调用的是d.NAME
5 类的属性在类的内部所有方法都可以调用到的
武sir补充:
1 创建一个类之后会把这个类保存在空间里面。实例化之后的对象也会开辟空间,存的是类的指针。
2 self是指调用当前方法的对象,self.NAME 是在这个对象的空间里面新建一个NAME ,在self上创建的属性都是保存的对象里面。
3
成员属性
成员属性可以在类里面定义 也可以在类外面定义,也可以在类外面调用 。谁定义的属性就只属于谁。
class Dog(object): def __init__(self,name): self.name = name def sayhi(self): print('hello,I am a dog.',self.name) d = Dog('二哈') d.age = 10 print(d.name) #二哈 print(d.age) #10
在类外部定义的属性,在类内部一样可以调用到,但是定义必须在调用之前
class Dog(object): def __init__(self,name): self.name = name def sayhi(self): print('hello,I am a dog.',self.age) d = Dog('二哈') d.age = 10 d.sayhi() #hello,I am a dog. 10
私有属性
不能被类外部直接访问的属性叫做私有属性。
私有属性的定义:__private_attr_name = value 前面两个下划线必须要的。
class Dog(object): def __init__(self,name): self.name = name self.__weight = 100 d = Dog('二哈') print(d.__weight) # AttributeError: 'Dog' object has no attribute '__weight'
如果要得到这个私有属性的值,可以通过函数返回的方法。
class Dog(object): def __init__(self,name): self.name = name self.__weight = 100 def sayhi(self): print('my wigth is ', self.__weight,) def getWeight(self): return self.__weight d = Dog('二哈') d.sayhi() #my wigth is 100 类内调用私有属性 print(d.getWeight()) # 100 通过内部方法返回私有属性的值
强制访问私有属性
print(d._Dog__weight) #100
公有属性
所有对象都能访问的属性,即在类里直接定义的属性。
class Dog(object): type='dog' #定义一个公有属性 def __init__(self,name): self.name = name self.__weight = 100 def sayhi(self): print('my wigth is ', self.__weight,) def getWeight(self): return self.__weight d = Dog('二哈') d2 = Dog('秋田') print(d.type) #dog print(d2.type) #dog d.type = 'mao' #修改d的公有属性 print(d.type) #mao print(d2.type) #dog Dog.type = 'houzi' #通过类修改公有属性 print(d.type) #mao print(d2.type) #houzi
通过类名修改公有属性是修改所有对像的这个公有属性,默认都是引用类的公有属性。
如果某个对象修改了自己的这个公有属性,那么相当于重新创建了一个自己的成员属性,那么类的公有属性跟这个对象就没有关系了。就算是修改类的公有属性也不会影响到这个对象。
调用公有属性的方式和方法是一样的,都是通过类指针先找到类,然后在调用这个公有属性。公有属性是属于类的,只存一份在类里面就好,对象里面封装的是普通属性。
封装:
1、类中封装了:属性、方法
2 、对象封装了:普通属性
继承:
重点是self是当前对象。 当前对象是指当前调用这个方法的对象。
obj调用的a1(),F3没有 a1()就去 F2里面找,a1()又用self 调用a2() , 这里的self就是obj,obj又是F3的对象,所以要到f3找a2()