各位用户为了找寻关于深入讲解Python中面向对象编程的相关知识的资料费劲了很多周折。这里教程网为您整理了关于深入讲解Python中面向对象编程的相关知识的相关资料,仅供查阅,以下为您介绍关于深入讲解Python中面向对象编程的相关知识的详细内容
Python从第一天开始就是面向对象的语言。正因为如此,创建和使用类和对象是非常地容易。本章将帮助您在使用Python面向对象编程的技术方面所有提高。
如果没有任何以往面向对象(OO)的编程的经验,那么可能要了解一些基本的入门课程就可以了,或者至少某种形式的教程,让你有了解基本概念。
但是,这里会比较少地介绍面向对象编程(OOP): OOP术语概述
类: 用户定义的原型对象,它定义了一套描述类的任何对象的属性。属性是数据成员(类变量和实例变量)和方法,通过点符号访问。 类变量:这是一个类的所有实例共享的变量。类变量在类,但外面的任何类的方法定义。类变量不被用作经常作为实例变量。 数据成员:保存与类和对象关联的数据的类变量或实例变量。 函数重载:一个以上的行为特定功能的分配。执行的操作所涉及的对象(自变量)的类型不同而不同。 实例变量:所定义的方法内,只属于一个类的当前实例的变量。 继承:类的特点,即都是由它派生其他类的转移。 实例:某一类的一个单独对象。属于类Circle一个obj对象,例如,是类Circle的一个实例。 实例化:创建一个类的实例。 Method : 一种特殊的函数,函数在类定义中定义。 对象:这是由它的类中定义的数据结构的唯一实例。一个对象包括两个数据成员(类变量和实例变量)和方法。 运算符重载:一个以上的函数功能,特定的操作符分配。创建类:
类语句将创建一个新的类定义。类的名称紧跟在关键字class后跟一个冒号,如下所示:
? 1 2 3class
ClassName:
'Optional class documentation string'
class_suite
类有一个文档字符串,它可以通过类名.__ doc__访问。
class_suite由所有定义的类成员,数据属性与函数组件的语句。
例子
下面是一个简单的Python类的例子:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14class
Employee:
'Common base class for all employees'
empCount
=
0
def
__init__(
self
, name, salary):
self
.name
=
name
self
.salary
=
salary
Employee.empCount
+
=
1
def
displayCount(
self
):
print
"Total Employee %d"
%
Employee.empCount
def
displayEmployee(
self
):
print
"Name : "
,
self
.name,
", Salary: "
,
self
.salary
empCount是一个类变量,其值将是这个类的所有实例共享。这可以从类中或外部进行访问,访问形式为 Employee.empCount。
第一个方法__init__()是一种特殊的方法,这就是所谓的类构造函数或当创建该类的一个新实例Python调用的初始化方法。
声明就像正常函数中一样,不同的是第一个参数到每个方法是类的方法。 Python增加了self参数列表;不需要把调用的方法都它列入。
创建实例对象:
要创建一个类的实例,调用类名并传递任何参数给__init__方法接收。
? 1 2 3 4"This would create first object of Employee class"
emp1
=
Employee(
"Zara"
,
2000
)
"This would create second object of Employee class"
emp2
=
Employee(
"Manni"
,
5000
)
访问属性:
可以访问使用点运算符来访问对象的属性。而类变量使用类名来访问,如下所示:
? 1 2 3emp1.displayEmployee()
emp2.displayEmployee()
print
"Total Employee %d"
%
Employee.empCount
现在,把所有的概念放在一起:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24#!/usr/bin/python
class
Employee:
'Common base class for all employees'
empCount
=
0
def
__init__(
self
, name, salary):
self
.name
=
name
self
.salary
=
salary
Employee.empCount
+
=
1
def
displayCount(
self
):
print
"Total Employee %d"
%
Employee.empCount
def
displayEmployee(
self
):
print
"Name : "
,
self
.name,
", Salary: "
,
self
.salary
"This would create first object of Employee class"
emp1
=
Employee(
"Zara"
,
2000
)
"This would create second object of Employee class"
emp2
=
Employee(
"Manni"
,
5000
)
emp1.displayEmployee()
emp2.displayEmployee()
print
"Total Employee %d"
%
Employee.empCount
当执行上面的代码,产生以下结果:
? 1 2 3Name : Zara ,Salary:
2000
Name : Manni ,Salary:
5000
Total Employee
2
在任何时候可以添加,删除或修改类和对象的属性:
? 1 2 3emp1.age
=
7
# Add an 'age' attribute.
emp1.age
=
8
# Modify 'age' attribute.
del
emp1.age
# Delete 'age' attribute.
除了使用正常的语句来访问属性,可以使用以下函数:
getattr(obj, name[, default]) : 访问对象的属性。 hasattr(obj,name) : 检查一个属性是否存在。 setattr(obj,name,value) : 设置一个属性。如果属性不存在,那么它将被创建。 delattr(obj, name) : 要删除一个属性。 ? 1 2 3 4hasattr
(emp1,
'age'
)
# Returns true if 'age' attribute exists
getattr
(emp1,
'age'
)
# Returns value of 'age' attribute
setattr
(emp1,
'age'
,
8
)
# Set attribute 'age' at 8
delattr
(empl,
'age'
)
# Delete attribute 'age'
内置的类属性:
每个Python类会继续并带有内置属性,他们可以使用点运算符像任何其他属性一样来访问:
__dict__ : 字典包含类的命名空间。 __doc__ : 类的文档字符串,或None如果没有定义。 __name__: 类名称。 __module__: 在类中定义的模块名称。此属性是在交互模式其值为“__main__”。 __bases__ : 一个可能是空的元组包含了基类,其在基类列表出现的顺序。对于上面的类,尝试访问这些属性:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22#!/usr/bin/python
class
Employee:
'Common base class for all employees'
empCount
=
0
def
__init__(
self
, name, salary):
self
.name
=
name
self
.salary
=
salary
Employee.empCount
+
=
1
def
displayCount(
self
):
print
"Total Employee %d"
%
Employee.empCount
def
displayEmployee(
self
):
print
"Name : "
,
self
.name,
", Salary: "
,
self
.salary
print
"Employee.__doc__:"
, Employee.__doc__
print
"Employee.__name__:"
, Employee.__name__
print
"Employee.__module__:"
, Employee.__module__
print
"Employee.__bases__:"
, Employee.__bases__
print
"Employee.__dict__:"
, Employee.__dict__
当执行上面的代码,产生以下结果:
? 1 2 3 4 5 6 7 8 9Employee.__doc__: Common base
class
for
all
employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {
'__module__'
:
'__main__'
,
'displayCount'
:
<function displayCount at
0xb7c84994
>,
'empCount'
:
2
,
'displayEmployee'
: <function displayEmployee at
0xb7c8441c
>,
'__doc__'
:
'Common base class for all employees'
,
'__init__'
: <function __init__ at
0xb7c846bc
>}
销毁对象(垃圾回收):
Python的删除不需要的对象(内建类型或类的实例),自动释放内存空间。由Python定期回收的内存块不再使用的过程被称为垃圾收集。
Python的垃圾回收器在程序执行过程中运行,当一个对象的引用计数为零时触发。一个对象的引用计数改变为指向它改变别名的数量。
当它分配一个新的名字或放置在容器(列表,元组或字典)的对象的引用计数增加。当对象的引用计数减少使用 del 删除,其基准被重新分配,或者它的引用超出范围。当一个对象的引用计数变为零,Python会自动地收集它。
? 1 2 3 4 5 6 7a
=
40
# Create object <40>
b
=
a
# Increase ref. count of <40>
c
=
[b]
# Increase ref. count of <40>
del
a
# Decrease ref. count of <40>
b
=
100
# Decrease ref. count of <40>
c[
0
]
=
-
1
# Decrease ref. count of <40>
当垃圾回收器销毁孤立的实例,并回收其空间一般不会注意到。但是,一个类可以实现特殊方法__del__(),称为析构函数被调用时,该实例将被摧毁。这个方法可以用于清理所用的一个实例的任何非内存资源。 例子:
__del__()析构函数打印实例,它即将被销毁的类名:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17#!/usr/bin/python
class
Point:
def
__init(
self
, x
=
0
, y
=
0
):
self
.x
=
x
self
.y
=
y
def
__del__(
self
):
class_name
=
self
.__class__.__name__
print
class_name,
"destroyed"
pt1
=
Point()
pt2
=
pt1
pt3
=
pt1
print
id
(pt1),
id
(pt2),
id
(pt3)
# prints the ids of the obejcts
del
pt1
del
pt2
del
pt3
当执行上面的代码,它产生以下结果:
? 1 23083401324
3083401324
3083401324
Point destroyed
注意:理想情况下,应该定义类的单独的文件,那么应该使用import语句将其导入主程序文件。详细请查看Python- 模块章节,导入模块和类的更多细节。 类继承:
不用从头开始,可以通过上面列出的括号父类的新类名后,从一个已经存在的类派生它创建一个类。
子类继承父类的属性,可以使用父类的这些属性,就好像它们是在子类中定义的一样。子类也可以覆盖父类的数据成员和方法。 语法
派生类的声明很像它们的父类; 从基类的列表后给出类名继承:
? 1 2 3class
SubClassName (ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
例子
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28#!/usr/bin/python
class
Parent:
# define parent class
parentAttr
=
100
def
__init__(
self
):
print
"Calling parent constructor"
def
parentMethod(
self
):
print
'Calling parent method'
def
setAttr
(
self
, attr):
Parent.parentAttr
=
attr
def
getAttr
(
self
):
print
"Parent attribute :"
, Parent.parentAttr
class
Child(Parent):
# define child class
def
__init__(
self
):
print
"Calling child constructor"
def
childMethod(
self
):
print
'Calling child method'
c
=
Child()
# instance of child
c.childMethod()
# child calls its method
c.parentMethod()
# calls parent's method
c.
setAttr
(
200
)
# again call parent's method
c.
getAttr
()
# again call parent's method
当执行上面的代码,产生以下结果:
? 1 2 3 4Calling child constructor
Calling child method
Calling parent method
Parent attribute :
200
类似的方式,可以按如下继承多个父类的类:
代码如下: class A: # define your class A .....
class B: # define your calss B .....
class C(A, B): # subclass of A and B .....
可以使用issubclass()或isinstance()函数来检查两个类和实例的关系。
issubclass(sub, sup) 如果给定的子类子确实是超sup的子类布尔函数返回true。 isinstance(obj, Class) 如果obj是Class类的实例,或者是类的一个子类的实例布尔函数返回true重写方法:
可以覆盖父类的方法。原因之一重写父的方法,因为可能想在子类特殊或实现不同的功能。 例子
? 1 2 3 4 5 6 7 8 9 10 11 12#!/usr/bin/python
class
Parent:
# define parent class
def
myMethod(
self
):
print
'Calling parent method'
class
Child(Parent):
# define child class
def
myMethod(
self
):
print
'Calling child method'
c
=
Child()
# instance of child
c.myMethod()
# child calls overridden method
当执行上面的代码,产生以下结果:
? 1Calling child method
基础重载方法:
下表列出了一些通用的功能,可以在类重写中:
重载运算符:
假设要创建了一个Vector类来表示二维向量,当使用加运算符来增加他们发生了什么?最有可能是Python会屌你。
可以,但是定义__add__方法在类中进行矢量相加,再加上操作符的行为会按预期: 例子:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16#!/usr/bin/python
class
Vector:
def
__init__(
self
, a, b):
self
.a
=
a
self
.b
=
b
def
__str__(
self
):
return
'Vector (%d, %d)'
%
(
self
.a,
self
.b)
def
__add__(
self
,other):
return
Vector(
self
.a
+
other.a,
self
.b
+
other.b)
v1
=
Vector(
2
,
10
)
v2
=
Vector(
5
,
-
2
)
print
v1
+
v2
当执行上面的代码,产生以下结果:
? 1Vector(
7
,
8
)
数据隐藏:
对象的属性可以是或可以不在类定义外部可见。对于这些情况,可以命名以双下划线前缀属性,这些属性将无法直接让外部可视。 例子:
? 1 2 3 4 5 6 7 8 9 10 11 12 13#!/usr/bin/python
class
JustCounter:
__secretCount
=
0
def
count(
self
):
self
.__secretCount
+
=
1
print
self
.__secretCount
counter
=
JustCounter()
counter.count()
counter.count()
print
counter.__secretCount
当执行上面的代码,产生以下结果:
? 1 2 3 4 5 61
2
Traceback (most recent call last):
File
"test.py"
, line
12
,
in
<module>
print
counter.__secretCount
AttributeError: JustCounter instance has no attribute
'__secretCount'
Python的保护成员通过内部更改名称以包含类名。可以访问这些属性通过object._className__attrName。如果想更换最后一行,那么它会工作如下:
? 1 2.........................
print
counter._JustCounter__secretCount
当执行上面的代码,产生以下结果:
? 1 2 31
2
2