您的位置:首页 > 编程语言 > Python开发

Python面向对象编程

2017-04-02 11:27 281 查看
一、面向对象 面向对象程序设计(Object-oriented programming,OOP)是一种程序设计范式,也是一种程序开发方法。对象指的是类的实例,类是创建对象的模板,一个类可以创建很多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫做类的实例化。编程方法主要可以分为两类:面向过程与面向对象,他们的主要区别在于:
面向过程编程:以指令为核心,围绕“正在发生什么”进行编写,程序具有一系列线性步骤,主体思想是代码作用于数据。 面相对象编程(OOP):以数据为核心,围绕“将影响谁”进行编写,围绕数据及为数据严格定义的接口来组织程序, 用数据控制对代码的方向。
面向对象编程种主要有以下几个主要概念:
类:定义了被多个同一类型对象共享的结构和行为(数据和代码)。 对象:类的实例。既包含数据(变量,也称属性),也包含代码(函数,也称方法)。 封装:隐藏实现方案细节;将代码及处理的数据绑定在一起的一种编程机制,用于保证程序和数据不受外部干扰且不会被误用。
继承:一个对象获得另一个对象属性的过程,用于实现按层分类的概念;一个深度继承的子类继承了类层次中它的每个先祖的所有属性;超类、基类、父类,子类、派生类。
多态:允许一个接口被多个通用的类动作使用的特性,具体使用哪个动作与应用场合相关;“一个接口上,多种方法”:用于为一组相关的动作设计一个通用的接口,以降低程序复杂性。
二、类的创建使用class关键字创建类
超类是一个或多个用于继承的父类的集合类体中可以包含:声明语句、类成员定义、数据属性、方法。
Class ClassName(bases):          #不存在继承关系时,可以不提供bases
'class documentation string'   #类文档可选
Data = value                   #定义数据属性
def method(self , ...)         #定义方法属性
self.member = value

class MyClass():
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
类方法及调用
实例(对象)通常包含属性和方法。
数据属性:即变量 可调用的方法:object.method(),即函数 在OOP中,实例就像是带有”数据”的记录,而类是处理这些记录的”程序”。通过实例调用方法相当于调用所属类的方法来处理当前实例,类似obj.method(arg...)自动转为class.method(instance, args...);因此在类中每个方法必须具有 self 参数,它隐含当前实例之意;在方法内对self属性做赋值运算会产生每个实例的属性;没有实例,方法就不允许调用。
In [1]: class MyClass():
...:         """A simple example class"""
...:         i = 12345
...:         def f(self):
...:                 return 'hello world'
...:
In [2]: x=MyClass()       #实例化一个类
In [3]: x.f()             #调用类的方法
Out[3]: 'hello world'
In [4]: x.i
Out[4]: 12345
In [5]: x.i=23456         #修改成员变量
In [6]: x.i
Out[6]: 23456
构造函数与析构函数
构造函数:创建实例时,python 会自动调用类中的__init__方法,以隐性的为实例提供属性__init__方法被称为构造器,如果类中没有定义__init__方法,实例创建之初仅是一个简单的名称空间。构造函数不能有返回值。
In [8]:  class Myclass(object):
...:    message='Hello,Developer'
...:    def show(self):
...:       print(self.message)
...:
In [9]:  class Myclass(object):
...:    message='Hello,Developer'
...:    def show(self):
...:       print(self.message)
...:    def __init__(self):                #构造函数
...:       print('Constructor is called')
...:
In [10]: inst=Myclass()       #当Myclass类实例化时,自动执行了构造函数
Constructor is called
In [11]: inst.show()
Hello,Developer
析构函数:__del__方法被称为析构函数,在销毁(释放)对象时将调用它们。析构函数往往用来做"清理善后"工作,如数据库链接对象可以在析构函数中释放对数据库资源的占用。
In [17]:  class Myclass1(object):
...:    message='Hello,Developer'
...:    def show(self):
...:       print(self.message)
...:    def __init__(self):
...:       print('Constructor is called')
...:    def __del__(self):
...:       print('Destructor is called!')
...:
In [18]: inst1=Myclass1()        #实例化类
Constructor is called
In [19]: inst1.show()
Hello,Developer
In [20]: del inst1               #析构函数
Destructor is called!
类的特殊属性:可以使用类的__dict__字典属性或内置的 dir()函数来获取类的属性。
In [27]: dir(Myclass1)      #查看类所拥有的属性和方法
Out[27]:
['__class__',
'__del__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'message',
'show']
实例属性(成员变量)

实例仅拥有数据属性(方法是类属性),通常通过构造器”__init__”为实例提供属性;这些数据属
性独立于其他实例或者类;实例释放时,其属性也将被清除。内建函数 dir()或者实例的特殊属性 __dict__可用于查看实例属性。
In [31]: class Myclass2(object):
...:         message='Hello,Developer'            #类成员属性
...:         def show(self):
...:           print(self.message)                #实例成员变量
...:           print('Here is %s in %s' %(self.name,self.color))
...:         def __init__(self,name='unset',color='black'):
...:           print('Constructor is called with parms:',name,'',color)
...:           self.name=name
...:           self.color=color
...:
In [32]: Myclass2.message                #输出类变量
Out[32]: 'Hello,Developer'
In [33]: Myclass2.message='Hello Python' #更改类成员变量
In [34]: Myclass2.message
Out[34]: 'Hello Python'
In [35]: init3=Myclass2()                #实例化类Myclass2
Constructor is called with parms: unset  black
In [36]: init3.message                   #访问类成员变量
Out[36]: 'Hello Python'
In [37]: init3.message='Hello'           #更改类成员变量
In [39]: Myclass2.message                #可以发现,实例对象无法更改类成员对象
Out[39]: 'Hello Python'
类方法中的可用变量

实例变量:指定变量名称及示例自身进行引用;self.变量名
局部变量:方法内部创建的变量,可以直接使用
类变量(静态变量):通过指定变量名与类名进行引用;类名.变量名
全局变量:直接使用
类成员的修饰符
公有成员,在任何地方都能访问
私有成员,只有在类的内部才能方法
class C:
classname = '公有变量'    #类的公有字段,即变量
__classfoo = "私有变量"   #类的私有字段,使用__开头声明的变量为私有变量
def __init__(self):
self.name = '公有变量'    #对象的公有字段,即变量
self.__foo = "私有变量"   #对象的私有字段,使用__开头声明的变量为私有变量
静态字段(属于类)
公有静态变量:类可以访问;类内部可以访问;派生类中可以访问
私有静态变量:仅类内部可以访问
普通字段(属于对象)
公有普通变量:对象可以访问;类内部可以访问;派生类中可以访问
私有普通变量:仅类内部可以访问
In [42]: class Myclass2(object):
...:         message='Hello,Developer'            #类成员
...:         __classname='Python'
...:         def show(self):
...:           print(self.message)
...:           print('Here is %s in %s' %(self.name,self.color))
...:         def __init__(self,name='unset',color='black'):
...:           print('Constructor is called with parms:',name,'',color)
...:           self.name=name
...:           self.__color=color
In [43]: inst4=Myclass2()             #实例化类
Constructor is called with parms: unset  black
In [44]: inst4.message                #实例化的对象可以访问类的公有变量
Out[44]: 'Hello,Developer'
In [45]: inst4.__classname            #实例化的对象无法访问类的私有变量
--------------------------------------------------------------------------
AttributeError                           Traceback (most recent call last)
<ipython-input-45-379f39c829cf> in <module>()
----> 1 inst4.__classname
In [47]: inst4.name                   #实例对象可以访问对象公有变量
Out[47]: 'unset'
In [48]: inst4.__color                #实例对象无法外部访问对象私有变量
--------------------------------------------------------------------------
AttributeError                           Traceback (most recent call last)
<ipython-input-48-5db61d225aac> in <module>()
----> 1 inst4.__color
AttributeError: 'Myclass2' object has no attribute '__color'
o 静态函数和类函数
Python中支持两种基于类名访问成员的函数:静态函数和类函数,它们的不同点是类函数有一个隐性参数cls可以用来获取信息,而静态函数没有该参数。静态函数使用装饰器@staticmethod定义,类函数使用装饰器@classmethod定义。
class Myclass(object):
message='Hello,Developer'
def show(self):
print('self.message')
print('Here is %s in %s !' %(self.name,self.color))

@staticmethod           #定义静态函数,可以访问类成员变量
def printMessage():
print('print Message is called ')
print(Myclass.message)

@classmethod            #定义类函数,第一个参数必须是cls
def creatobj(cls,name,color):
print('Object will be created: %s(%s,%s)' %(cls.__name__,name,color))
return cls(name,color)
def __init__(self,name='unset',color='black'):
print('Constructor is called with params:',name,'',color)
self.anme=name
self.color=color

def __def__(self):
print('Destructor is called for %s' %self.name)

Myclass.printMessage()     #直接调用静态函数
inst=Myclass.creatobj('Toby', 'Red')
print(inst.message)

输出结果:
print Message is called      #静态函数输出结果
Hello,Developer
Object will be created: Myclass(Toby,Red)     #类函数输出结果
Constructor is called with params: Toby  Red  #构造函数
Hello,Developer              #print输出
三、继承与多态
类之间的继承是面向对象的设计的重要方法,通过继承可以达到简化代码和优化设计模式的目的。
Python类在定义时可以在小括号中指定基类。所有Pyhon类都是object类型的子类。
class BaseClass(object)           #父类定义
block_class
class SubClass(BaseClass)         #子类定义
block_class
新式类与经典类

在Python中存在两种类,经典类与新式类,它们的区别在于:
1)写法不一样

class A:           #经典类
pass
class B(object):   #新式类
pass


Python 2.x中默认都是经典类,只有显式继承了object才是新式类
Python 3.x中默认都是新式类,不必显式的继承object

2)在多继承中,继承搜索的顺序发生了改变,经典类多继承属性搜索顺序: 先深入继承树左侧,再
返回,开始找右侧;新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动

3)新式类更符合OOP编程思想,统一了python中的类型机制。

新式类对象可以直接通过__class__属性获取自身类型:type
新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定的范围之中
新式类增加了__getattribute__方法
class BaseA(object):
def move(self):
print('move called in BaseA')

class BaseB(object):
def move(self):
print('move called in BaseB')
class BaseC(BaseA):
def move(self):
print('move called in BaseC')

class Sub(BaseC,BaseB):
def move(self):
print('move called in Sub')
inst=Sub()
inst.move()
在此新式类的多重继承当中,当子类继承了多了父类并且调用共有的方法时,Python解释器会选择最近的一个基类成员方法。上面的例子move()搜索顺序为Sub、BaseC、BaseA、BaseB。
类与实例的内建函数

issubclass() 布尔函数,判断一个类是否由另一个类派生。issubclass(sub,sup)
isinstance() 布尔函数,判断一个对象是否是给定类的实例。isinstance(obj1,class_obj2)
hasattr() 布尔函数,判断一个对象是否拥有指定的属性,hasattr(obj , ‘attr’)
同类的函数还有 getattr()、setattr()、delattr()
super() 在子类中找出其父类以便于调用其属性;一般情况下仅能采用非绑定方式调用祖先方法;super()可用于传入实例或类型对象,super(type[,obj ])
In [1]: class Person():
...:     def __init__(self,name):
...:         self.name=name
...:
In [2]: class EmailPerson(Person):
...:     def __init__(self,name,email):
...:         super.__init__(name)
...:         self.email=email
上例中,子类EmailPerson通过super()方法获取了父类Person的定义,子类的__init__()调用了
Person.__init__()方法。它会自动将self参数传递给父类。这样不仅可以继承父类中的定义方法,还
可以创建子类独有的属性。
运算符重载

在方法中拦截内置的操作——当类的实例出现在内置函数中,Python 会自动调用自定义的方法,并
且返回自定义方法的操作结果。运算符重载让类拦截常规的 Pyhton 运算:类可以重载所有表达式
运算符;类也可以重载打印、函数调用、属性点运算等内置操作;载使类实例的行为项内置类型,重
载通过提供特殊名称的类方法实现。
特殊方法制定类

除了__init__和__del__之外,Python 类支持许多特殊方法,特殊方法都是以双下划线开头和结尾, 有些特殊方法有默认行为,没有默认行为的是为了留到需要的时候再实现.这些特殊的方法是python
中用来扩充类的强大工具, 他们可以实现: 模拟标准类型,重载操作符特殊方法允许类通过重载标
准操作符+,*甚至包括下标及映射操作[]来模拟标准类型.

方法重载调用
__init__构造函数对象建立:x=class(args)
__del__析构函数x对象对象
__add__运算符+如果没有_iadd_,x+y,x+=y
__or__运算符:(位OR)如果没有_ior_,x|y,x|=y
__repr__,__str__打印,转换print(x),repr(x),str(x)
__call__函数调用x(*args,**kargs)
__getattr__点运算符x.undefined
__setattr__属性赋值语句x.any=value
__delattr__属性删除del x.any
__getattribute__
属性获取x.any
__getitem__
索引运算x[key],x[i:j],没有__iter__时的for循环
__setitem__
索引赋值运算x[key]=value,x[i:j]=sequence
__delitem__
索引和切片删除del x[key],del[i:j]
__len__
长度len(x),如果没有__bool__真值测试
__bool__
布尔测试bool(x),真测试
__lt,__gt__
特定的比较x<y,x>y,x<=y,x>=y,x==y,x!=y
__le__,__ge__
__eq__,__ne__
__radd__右侧加法other+x
__iadd__
实地(增强的)加法x+=y
__iter__,__next__
迭代环境I=iter(x),next(I)
__contains__
成员关系测试item in x
__index__
整数值hex(x),bin(x),oct(x),o[x]
__enter__,__exit__
上下文管理器with obj as var:
__get__,__set__
描述运算符x.attr,x.attr=value,del x.attr
__delete__
删除在__del__之后删除对象
__new__
创建在__init__之前创建对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  对象 静态函数