什么是面向对象?
面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法:类中定义的函数。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
-
继承:即一个派生类(derived class)继承基类(base
class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。 - 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
面向对象一定要有类,以下介绍均基于类
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
属性,就是数据,包括类变量和实例变量
方法,就是操作数据的行为,包括实例方法、类方法和静态方法
为什么要使用类呢?
每个类都是一个模板,统一存储数据和操作数据的规则
每个类都是一个类别,基于这个类别管理数据,方便查找和操作
基于类可以实现继承和多态,方便程序的扩展
类作为一个整体,把一组组相关数据放到类的实例里面,进行存储,计算等,实现安全性、独立性,规则的操作统一,保证数据的一致性和完整性。
什么是封装?
将对象的数据与操作数据的方法相结合,通过方法将对象的数据与实现细节保护起来,就称为封装。外界只能通过对象的方法访问对象,因此封装同时也实现了对象的数据隐藏。通过封装和数据隐藏机制,将一个对象相关的变量和方法封装为一个独立的软件体,单独进行实现和维护,并使对象能够在系统内方便地进行传递,另外也保证了对象数据的一致性并使程序易于维护,封装可以让调用者不用关心对象是如何构建的而直接进行使用。
函数和类中的方法都可以实现封装,那么他们有什么区别呢?
类:
专有数据(可以存储,和对外使用)
方法(用于操作专有数据的),实现操作数据的规则。类实例不但有操作某些数据的过程和算法,且保存相关的数据
函数:
无专有数据,谁给他传值都可以处理,并返回,函数只有操作某些数据的过程和算法,但本身不能存储数据。
所以类和函数的区别在于是否保存数据
一个简单的类的例子:
class P:
def __init__(self,value): #构造方法,初始化用的
self.value = value #value局部变量
#self.value叫做实例变量
p =P(10)
print(p.value) #打印10
两个下划线开头的方法或者是变量,都是私有的。
私有的变量和方法,只能类内部的方法去调用,外部不可以
拿上面的例子说,如果是self.__value = value,print(p.__value),这样就会报错,因为外部不能使用类里的私有变量
类:
一组数据(可以是0个、1个或多个),以及提供操作这组数据的相关方法,数据和方法组成了类。
类定义的所有内容,在内存中仅有一份(类变量和类方法)
类实例(多个),每个类实例在内存中都有自己的空间。
类名全大写
class PERSON(object):
def __init__(self,name,sex,height,weight,bachelor):
self.name = name
self.sex = sex
self.height = height
self.weight = weight
self.bachelor = True
def print_name(self):
print(self.name)
alex = PERSON("Alex","M",180,200,True)
mike = PERSON("Mike","M",101,250,False)
print(alex.weight)
print(mike.weight)
alex.weight += 1
print(alex.weight)
alex.print_name()
类的方法里面为啥要有个self呢?
alex.print_name()---->在内存中找到类定义所在的内存位置,找到类里面定义的方法print_name(),self—>alex所在的内存地址,使用alex实例中的name值进行打印。
类:存储、管理、操作一组特定的数据的。通过私有变量和相应的操作方法,来保证数据的一致性和完整性。
保证数据的安全性有2种方法:
方法1:
设定私有变量__xxx,通过get_xxx()取数据,通过set_xxx赋值
取数据和设置数据的规则都在方法里。
__xxx是安全的,只能通过实例方法去访问。
方法2:
使用公有变量,通过@property 来读取数据,
通过@xxxx.setter来设置数据。
数据也是安全的,因为有2个方法来设定取数据和修改数据规则。
class Goods(object):
def __init__(self,pri):
self.pri = pri
@property
def price(self):
return int(self.pri)
@price.setter
def price(self, value):
if self.pri>=100 or self.pri<0:
return None
@price.deleter
def price(self):
print("价格变量被删除了!")
del self.pri
#调用
obj = Goods(50.50)
print(obj.price) # 自动执行 @property 修饰的 price 方法,并获取方法的返回值,打印50
obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数
print(obj.price) #打印50
del obj.price # 自动执行 @price.deleter 修饰的 price 方法,打印 价格变量被删除了!
类的特殊成员
1.__doc__表示类的描述信息
2.__module__表示当前操作的对象在哪个模块
3.__class__表示当前操作的对象的类是什么
4.__del__析构方法,当对象在内存中被释放时,自动触发执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关系内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
5.__call__对象后面加括号,触发执行
注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或类()()
6.__dict__类或对象中的所有成员
类的普通字段属于对象;类中的静态字段和方法等属于类
7.__str__如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。
8.
getitem
、
setitem
、__delitem__用于索引操作,如字典。以上分别表示获取、设置、删除数据
9.
getslice
、
setslice
、
delslice__在python2.7可以使用,在3.x已经被去掉了,需要使用__getitem
、
setitem
、__delitem__和__getslice__来实现
10.
iter__用于迭代器,之所以列表、字段、元组可以进行for循环,是因为类型内部定义了__iter
11.__slot__限制实例可以使用的属性名称
12.__metaclass__用途较少
13.__new__在类准备将自身实例化时调用,
new
()方式始终都是类的静态方法,即使没有被加上静态方法装饰器
类实现了如下方法,就是可以迭代的对象
iter
()
next
()