面向对象(object-oriented :简称: OO) 至今还没有统一的概念 我这里把它定义为: 按人们 认识客观世界的系统思维方式,采用基于对象(实体) 的概念建立模型,模拟客观世界分析、设 计、实现软件的办法。
面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。 这种方法把软件系统中相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。
Python 面向对象
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。
如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。接下来我们先来简单的了解下面向对象的一些基本特征。
面向对象概念
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 实例变量:定义在方法中的变量,只作用于当前实例的类。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
类
类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象。
类(Class) 由3个部分构成
- 类的名称:类名
- 类的属性:一组数据
- 类的方法:允许对进行操作的方法 (行为)
举例
1)人类设计,只关心3样东西:
- 事物名称(类名):人(Person)
- 属性:身高(height)、年龄(age)
- 方法(行为/功能):跑(run)、打架(fight)
2)狗类的设计
- 类名:狗(Dog)
- 属性:品种 、毛色、性别、名字、 腿儿的数量
- 方法(行为/功能):叫 、跑、咬人、吃、摇尾巴
类的抽象
如何把日常生活中的事物抽象成程序中的类?
拥有相同(或者类似)属性和行为的对象都可以抽像出一个类
方法:一般名词都是类(名词提炼法)
定义类
使用class语句来创建一个新类,class之后为类的名称并以冒号结尾,如下实例:
class ClassName(object):
'类的帮助信息' #类文档字符串
class_suite #类体
类的帮助信息可以通过ClassName.__doc__查看。
class_suite 由类成员,方法,数据属性组成。
实例:定义一个People类
# 定义类
class People(object):
"""文档说明"""
# 类属性:实例对象和类对象可以同时调用
sex="男" #公有的类属性
country="中国"
__age=18 #共有私有属性
def __init__(self,name): # 实例方法,实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性
# 实例属性是实例对象特有的,类对象不能拥有
self.name=name #实例属性
@classmethod
def getCountry(cls): #类方法,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法
return cls.country
@classmethod
def setCountry(cls,country):
cls.country=country
@staticmethod
def getCountry(): #静态方法
return People.country
def hi(self): #普通方法
return "你好%s"%self.name
说明:
- 定义类时有2种:新式类和经典类,如Car为经典类,如果是Car(object)则为新式类
- 类名 的命名规则按照"大驼峰"
- 单下划线前缀:可以用来表明只供内部使用,非强制。当使用from <模块/包名> import *,那么以“ _ ”开头的名称都不会被导入, 除非模块或包中的“__all__”列表显式地包含了它们
- 单下划线后缀:大家习惯于用来避免与 Python 关键字的冲突
- 双下划线前缀:私有化,私有化并不是语法上的强制,而是 python 隐藏了私有字段的访问入口,所以我们可以在新的入口中访问到私有字段:使用 类名(对象)._类名__属性名 来访问
- 双下划线前后缀:保留给 Python 自用
一个类可以包含以下类型变量:
- 局部变量:在方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
- 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化(分配内存)。成员变量可以被类中的方法和特定类的语句访问。
- 类变量:类变量也声明在类中,方法体之外。
注:当类变量与成员变量重名时,在方法中优先使用成员变量,方法中使用成员变量使用self,self代表当前类的当前对象。
static(静态)
类的静态成员不依赖类的某一实例,可使用类名直接访问
1.类变量(静态变量)
当类第一次被加载(任何一个对象的声明,首先要加载类),该类的类变量就分配独立内存,直到程序结束被回收。静态成员是公共的。
比较 | 静态变量 | 成员变量 |
---|---|---|
作用域 | 当前类 | 当前类 |
生命周期 | 类加载到程序结束 | 从对象产生到对象回收 |
使用方法 | 类名.静态变量名 | 对象名.成员变量名 |
静态变量即类变量 成员变量即实例变量,对象实例化后才能使用
静态方法
-
访问静态方法:类名.方法名(参数列表)
经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法。 比如更改环境变量或者修改其他类的属性等能用到静态方法。
静态方法在同一个类中被调用时,类名可以省略。普通成员方法必须在对象实例化后才可以调用,
比较 | 静态方法 | 成员方法 |
---|---|---|
调用 | 类名.方法名(参数) | 对象名.方法名(参数) |
调用普通方法 | 不能直接调用 | 同一个类中可以调用 |
调用静态方法 | 类名.方法名(参数) | 类名.方法名(参数) |
访问静态变量 | 类名.静态变量名 | 类名.静态变量名 |
访问成员变量 | 不能直接访问 | 同一类中可以直接访问 |
self | 不能使用 | 可以使用 |
类方法
-
访问类方法:类名.方法名(参数列表)
我们要写一个只在类中运行而不在实例中运行的方法
class A(object):
def __init__(self, name):
self.name = name
def printd(self):
print(self.name)
@staticmethod
def smethod(*arg):
print('Static:', arg)
@classmethod
def cmethod(*arg):
print('Class:', arg)
>> > a = A(12)
>> > a.printd()
12
>> > a.smethod()
Static: ()
>> > a.cmethod()
Class: ( < class '__main__.A' > ,)
>> > A.printd()
TypeError: unbound method printd() must be called with A instance as first argument(got nothing instead)
>> > A.smethod()
Static: ()
>> > A.cmethod()
Class: ( < class '__main__.A' > ,)
python的常用内置方法
内置方法 | 说明 |
---|---|
__init__(self,...) | 初始化对象,在创建新对象时调用 |
__del__(self) | 释放对象,在对象被删除之前调用 |
__new__(cls,*args,**kwd) | 实例的生成操作 |
__str__(self) | 在使用print语句时被调用 |
__getitem__(self,key) | 获取序列的索引key对应的值,等价于seq[key] |
__len__(self) | 在调用内联函数len()时被调用 |
__cmp__(stc,dst) | 比较两个对象src和dst |
__getattr__(s,name) | 获取属性的值 |
__setattr__(s,name,value) | 设置属性的值 |
__delattr__(s,name) | 删除name属性 |
__getattribute__() | __getattribute__()功能与__getattr__()类似 |
__gt__(self,other) | 判断self对象是否大于other对象 |
__lt__(slef,other) | 判断self对象是否小于other对象 |
__ge__(slef,other) | 判断self对象是否大于或者等于other对象 |
__le__(slef,other) | 判断self对象是否小于或者等于other对象 |
__eq__(slef,other) | 判断self对象是否等于other对象 |
__call__(self,*args) | 把实例对象作为函数调用 |
__init__():
__init__方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的初始化。注意,这个名称的开始和结尾都是双下划线。
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
说明:__init__ 方法定义为取一个参数name(以及普通的参数self)。在这个__init__里,我们只是创建一个新的域,也称为name。注意它们是两个不同的变量,尽管它们有相同的名字。点号使我们能够区分它们。最重要的是,我们没有专门调用__init__方法,只是在创建一个类的新实例的时候,把参数包括在圆括号内跟在类名后面,从而传递给__init__方法。这是这种方法的重要之处。现在,我们能够在我们的方法中使用self.name域。这在sayHi方法中得到了验证。
__new__():
__new__()在__init__()之前被调用,用于生成实例对象.利用这个方法和类属性的特性可以实现设计模式中的单例模式.单例模式是指创建唯一对象吗,单例模式设计的类只能实例化一个对象.
class Singleton(object):
__instance = None # 定义实例
def __init__(self):
pass
def __new__(cls, *args, **kwd): # 在__init__之前调用
if Singleton.__instance is None: # 生成唯一实例
Singleton.__instance = object.__new__(cls, *args, **kwd)
return Singleton.__instance
__str__():
__str__()用于表示对象代表的含义,返回一个字符串.实现了__str__()方法后,可以直接使用print语句输出对象,也可以通过函数str()触发__str__()的执行.这样就把对象和字符串关联起来,便于某些程序的实现,可以用这个字符串来表示某个类
class Cat:
"""定义了一个Cat类"""
#初始化对象
def __init__(self, new_name, new_age):
self.name = new_name
self.age = new_age
def __str__(self):
return "%s的年龄是:%d"%(self.name, self.age)
__del__()
__del__称作析构方法
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为在Python中,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。在程序执行结束之后,执行此方法
class Foo:
def __del__(self):
print('run __del__')