讲解Python中面向对象编程的相关知识

   这篇文章主要介绍了深入讲解Python中面向对象编程的相关知识,是Python入门学习中的基础知识,需要的朋友可以参考下

  Python从第一天开始就是面向对象的语言。正因为如此,创建和使用类和对象是非常地容易。本章将帮助您在使用Python面向对象编程的技术方面所有提高。

  如果没有任何以往面向对象(OO)的编程的经验,那么可能要了解一些基本的入门课程就可以了,或者至少某种形式的教程,让你有了解基本概念。

  但是,这里会比较少地介绍面向对象编程(OOP):

  OOP术语概述

  类: 用户定义的原型对象,它定义了一套描述类的任何对象的属性。属性是数据成员(类变量和实例变量)和方法,通过点符号访问。

  类变量:这是一个类的所有实例共享的变量。类变量在类,但外面的任何类的方法定义。类变量不被用作经常作为实例变量。

  数据成员:保存与类和对象关联的数据的类变量或实例变量。

  函数重载:一个以上的行为特定功能的分配。执行的操作所涉及的对象(自变量)的类型不同而不同。

  实例变量:所定义的方法内,只属于一个类的当前实例的变量。

  继承:类的特点,即都是由它派生其他类的转移。

  实例:某一类的一个单独对象。属于类Circle一个obj对象,例如,是类Circle的一个实例。

  实例化:创建一个类的实例。

  Method : 一种特殊的函数,函数在类定义中定义。

  对象:这是由它的类中定义的数据结构的唯一实例。一个对象包括两个数据成员(类变量和实例变量)和方法。

  运算符重载:一个以上的函数功能,特定的操作符分配。

  创建类:

  类语句将创建一个新的类定义。类的名称紧跟在关键字class后跟一个冒号,如下所示:

  ?

1
2
3

class ClassName:
'Optional class documentation string'
class_suite

  类有一个文档字符串,它可以通过类名.__ doc__访问。

  class_suite由所有定义的类成员,数据属性与函数组件的语句。

  例子

  下面是一个简单的Python类的例子:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14

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

  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
3

emp1.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
3

Name : Zara ,Salary: 2000
Name : Manni ,Salary: 5000
Total Employee 2

  在任何时候可以添加,删除或修改类和对象的属性:

  ?

1
2
3

emp1.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
4

hasattr(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
9

Employee.__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
7

a = 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
2

3083401324 3083401324 3083401324
Point destroyed

  注意:理想情况下,应该定义类的单独的文件,那么应该使用import语句将其导入主程序文件。详细请查看Python- 模块章节,导入模块和类的更多细节。

  类继承:

  不用从头开始,可以通过上面列出的括号父类的新类名后,从一个已经存在的类派生它创建一个类。

  子类继承父类的属性,可以使用父类的这些属性,就好像它们是在子类中定义的一样。子类也可以覆盖父类的数据成员和方法。

  语法

  派生类的声明很像它们的父类; 从基类的列表后给出类名继承:

  ?

1
2
3

class 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
4

Calling 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

  当执行上面的代码,产生以下结果:

  ?

1

Calling 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

  当执行上面的代码,产生以下结果:

  ?

1

Vector(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
6

1
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
3

1
2
2

时间: 2024-10-03 03:53:58

讲解Python中面向对象编程的相关知识的相关文章

讲解Python中fileno()方法的使用

  这篇文章主要介绍了讲解Python中fileno()方法的使用,是Python入门中的基础知识,需要的朋友可以参考下 fileno()方法返回所使用的底层实现,要求从操作系统I/O操作的整数文件描述符. 语法 以下是fileno()方法的语法: ? 1 fileObject.fileno(); 参数 NA 返回值 此方法返回整数文件描述符. 例子 下面的例子显示fileno()方法的使用. ? 1 2 3 4 5 6 7 8 9 10 11 #!/usr/bin/python   # Ope

初步讲解Python中的元组概念

  这篇文章主要介绍了初步讲解Python中的元组概念,是Python入门中的基础知识,需要的朋友可以参考下 元组是不可变的Python对象序列.元组的序列就像列表.唯一的区别是,元组不能被改变,即元组是不可被修改.元组使用小括号,而列表使用方括号. 创建一个元组很简单,只要把不同的逗号分隔值,可以把括号中的这些逗号来分隔每个值.例如: ? 1 2 3 tup1 = ('physics', 'chemistry', 1997, 2000); tup2 = (1, 2, 3, 4, 5 ); tu

Python中处理字符串的相关的len()方法的使用简介

  这篇文章主要介绍了Python中处理字符串的相关的len()方法的使用简介,是Python入门的基础知识,需要的朋友可以参考下 len()方法返回字符串的长度. 语法 以下是len()方法的语法: ? 1 len( str ) 参数 NA 返回值 此方法返回的字符串的长度. 例子 下面的例子显示了len()方法的使用. ? 1 2 3 4 5 #!/usr/bin/python   str = "this is string example....wow!!!";   print

讲解Python中if语句的嵌套用法

  这篇文章主要介绍了讲解Python中if语句的嵌套用法,是Python入门当中的基础知识,需要的朋友可以参考下 可能有这样一种情况,当你想检查其他条件后一个条件解析为真.在这种情况下,可以使用嵌套的if结构. 在嵌套的 if 语句结构,可以在一个 if... elif... else 结构里面可有另外一个 if... elif... else 结构. 语法: 嵌套 if...elif...else 结构的语法可以是: ? 1 2 3 4 5 6 7 8 9 10 11 12 if expre

Python中列表的一些基本操作知识汇总

  这篇文章主要介绍了Python中列表的一些基本操作知识汇总,皆属于Python的基本功,需要的朋友可以参考下 Python最基本的数据结构是序列(列表/元组).一个序列中的每个元素都分配有一个数字- 它的位置或索引.第一个索引是0,第二个索引是1,依此类推. Python有6内置类型的序列,但最常见的是列表和元组,我们将在本教程中看到. 有一些东西可以使用所有序列类型来做.这些操作包括索引,切片,加,乘,并检查成员.此外,Python已经内置函数查找序列的长度和搜索它的最大和最小的元素. P

有关c# 调用vc++编写的非托管DLL、socket编程等相关知识的讲的比较详细的书籍

问题描述 有关c# 调用vc++编写的非托管DLL.socket编程等相关知识的讲的比较详细的书籍 学习c# 调用vc++编写的非托管DLL.socket编程等相关知识的讲的比较详细的书籍都有哪些?(最好是基于VS2008的) 解决方案 c#调用非托管C++生成的dllc# 调用 C++ 非托管 DllC#调用非托管dll 解决方案二: 这样一个知识点,最好是 Baidu/Google 查找来解决 书上的内容,没有网络上的丰富

Lua中函数与面向对象编程的基础知识整理_Lua

函数 1. 基础知识调用函数都需要写圆括号,即使没有参数,但有一种特殊例外:函数若只有一个参数且参数是字面字符串或table构造式,则圆括号可有可无,如dofile 'a.lua',f{x=10, y=20}. Lua为面向对象式的调用提供冒号操作符的特殊语法,如o.foo(o, x)等价于o:foo(x).和Javascript类似,调用函数时提供的实参数量可以与形参数量不同,若实参多了则舍弃,不足则多余的形参初始化为nil. 1.1 多重返回值 Lua允许函数返回多个结果,函数返回如retu

举例讲解Python中装饰器的用法_python

由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函数对象有一个__name__属性,可以拿到函数的名字: >>> now.__name__ 'now' >>> f.__name__ 'now' 现在,假设我们要增强now()函数的功能,比

以实例全面讲解PHP中多进程编程的相关函数的使用_php实例

    PHP有一组进程控制函数(编译时需要–enable-pcntl与posix扩展),使得php能实现跟c一样的创建子进程.使用exec函数执行程序.处理信号等功能.     <?php header('content-type:text/html;charset=utf-8' ); // 必须加载扩展 if (!function_exists("pcntl_fork")) { die("pcntl extention is must !"); } //总