开发手册 欢迎您!
软件开发者资料库

Python 3 - 面向对象

Python 3面向对象 - 从简单和简单的步骤学习Python 3,从基本到高级概念,包括Python 3语法面向对象语言,概述,环境设置,基本语法,变量类型,基本运算符,决策,循环,方法,字符串,列表,元组,字典,日期和时间,函数,模块,文件I / O,工具/实用程序,异常处理,正则表达式,CGI编程,MySQL数据库访问,网络编程,使用SMTP发送电子邮件,多线程编程,套接字,GUI,扩展,XML编程。

自从它存在以来,Python一直是面向对象的语言.因此,创建和使用类和对象非常简单.本章帮助您成为使用Python面向对象编程支持的专家.

如果您以前没有任何面向对象(OO)编程经验,您可能需要咨询关于它的入门课程或至少是某种教程,以便掌握基本概念.

但是,这里是面向对象编程(OOP)的一个小介绍.帮助你减去;

OOP术语概述

  • Class : 用户定义的对象原型,它定义了一组表征该类任何对象的属性.属性是数据成员(类变量和实例变量)和方法,可通过点表示法访问.

  • 类变量 : 由类的所有实例共享的变量.类变量在类中定义,但在类的任何方法之外.类变量的使用频率与实例变量不同.

  • 数据成员 : 包含与类及其对象关联的数据的类变量或实例变量.

  • 函数重载 : 为特定函数分配多个行为.执行的操作因所涉及的对象或参数类型而异.

  • 实例变量 : 在方法内定义的变量,仅属于类的当前实例.

  • 继承 : 将类的特征转移到从中派生的其他类.

  • 实例 : 某个班级的个别对象.例如,属于Circle类的对象obj是Circle类的实例.

  • Instantiation : 创建类的实例.

  • 方法 : 一种在类定义中定义的特殊函数.

  • 对象 : 由其类定义的数据结构的唯一实例.对象包括数据成员(类变量和实例变量)和方法.

  • 运算符重载 : 为特定运算符分配多个函数.

创建类

class 语句创建一个新的类定义.该类的名称紧跟在关键字 class 之后,后跟冒号,如下 :

class ClassName:   'Optional class documentation string'   class_suite


  • 该课程有文档字符串,可以通过 ClassName .__ doc __ 访问.

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

示例

以下是一个简单的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)


  • 变量 empCount 是一个类变量,其值在所有之间共享本课程中的a个实例.这可以从类内部或类外部作为 Employee.empCount 访问.

  • 第一种方法 __ init __( )是一种特殊的方法,它被称为类构造函数或初始化方法,当你创建这个类的新实例时Python会调用它.

  • 你声明其他类方法,如普通函数,但每个方法的第一个参数是 self . Python将 self 参数添加到列表中;调用方法时不需要包含它.

创建实例对象

要创建类的实例,可以使用类名调用该类,并传入其 __ init __ 方法接受的任何参数.

This would create first object of Employee classemp1 = Employee("Zara", 2000)This would create second object of Employee classemp2 = Employee("Manni", 5000)


访问属性

使用点运算符和对象访问对象的属性.使用类名访问类变量如下 :

emp1.displayEmployee()emp2.displayEmployee()print ("Total Employee %d" % Employee.empCount)


现在,将所有概念放在一起&减去;

#!/usr/bin/python3class 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)


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

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


您可以随时添加,删除或修改类和对象的属性;

emp1.salary = 7000  # Add an 'salary' attribute.emp1.name = 'xyz'  # Modify 'age' attribute.del emp1.salary  # Delete 'age' attribute.


您可以使用以下函数 :

  • getattr(obj,name [,default]) : 访问对象的属性.

  • hasattr(obj,name) : 检查属性是否存在.

  • setattr(obj,name,value) : 设置属性.如果属性不存在,那么它将被创建.

  • delattr(obj,name) : 删除属性.

hasattr(emp1, 'salary')    # Returns true if 'salary' attribute existsgetattr(emp1, 'salary')    # Returns value of 'salary' attributesetattr(emp1, 'salary', 7000) # Set attribute 'salary' at 7000delattr(emp1, 'salary')    # Delete attribute 'salary'


内置类属性

每一个Python类保持跟随内置属性,并且可以使用点运算符访问它们,就像任何其他属性 :

  • __ dict __ : 包含类名称空间的字典.

  • __ doc __ : 类文档字符串或无,如果未定义.

  • __ name __ : 班级名称.

  • __ module __ : 定义类的模块名称.此属性在交互模式下为"__main__".

  • __ bases __ : 一个可能为空的元组,包含基类,按它们在基类列表中出现的顺序排列.

对于上面的类让我们尝试访问所有这些属性 :


#!/usr/bin/python3class 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)emp1 = Employee("Zara", 2000)emp2 = Employee("Manni", 5000)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__ )


执行上述代码时,会产生以下结果 :

Employee.__doc__: Common base class for all employeesEmployee.__name__: EmployeeEmployee.__module__: __main__Employee.__bases__: (,)Employee.__dict__: {   'displayCount': ,    '__module__': '__main__', '__doc__': 'Common base class for all employees',    'empCount': 2, '__init__':    , 'displayEmployee':    ,   '__weakref__':    , '__dict__':    }


销毁对象(垃圾收集)

Python删除不需要的对象(内置类型或类实例)自动释放内存空间. Python定期回收不再使用的内存块的过程称为垃圾收集.

Python的垃圾收集器在程序执行期间运行,并在对象的引用计数达到零时触发.对象的引用计数随着指向它的别名数量的变化而变化.

对象的引用计数在分配新名称或放在容器中时会增加(列表,元组或字典).当使用 del 删除对象的引用计数时,对象的引用计数会减少,其引用将被重新分配,或者其引用超出范围.当对象的引用计数达到零时,Python会自动收集它.

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 __()析构函数打印类名即将被销毁和减去的实例;

#!/usr/bin/python3class 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 = pt1pt3 = pt1print (id(pt1), id(pt2), id(pt3))   # prints the ids of the obejctsdel pt1del pt2del pt3


执行上述代码时,会产生以下结果 :

140338326963984 140338326963984 140338326963984Point destroyed


注意 : 理想情况下,您应该在单独的文件中定义类,然后使用 import 语句将它们导入主程序文件中.

在上面的示例中,假设Point类的定义包含在 point.py 中,其中没有其他可执行代码.

#!/usr/bin/python3import pointp1 = point.Point()


类继承

您可以通过在新类名后面的括号中列出父类,而不是从头开始,通过从预先存在的类派生它来创建类.

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

语法

派生类的声明与其父类非常相似;但是,在类名和减号之后给出了要继承的基类列表;

class SubClassName (ParentClass1[, ParentClass2, ...]):   'Optional class documentation string'   class_suite


示例

#!/usr/bin/python3class 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 childc.childMethod()      # child calls its methodc.parentMethod()     # calls parent's methodc.setAttr(200)       # again call parent's methodc.getAttr()          # again call parent's method


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

Calling child constructorCalling child methodCalling parent methodParent 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)如果给定的子类 sub 确实是超类 sup 的子类,则布尔函数返回True.

  • isinstance(obj,Class)布尔函数返回True,如果 obj 是类类的实例或是Class的子类的实例

重写方法

你总是可以覆盖您的父类方法.覆盖父方法的一个原因是您可能需要子类中的特殊或不同功能.

示例

#!/usr/bin/python3class 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 childc.myMethod()         # child calls overridden method


执行上述代码时,它产生以下结果 :

Calling child method


基本重载方法

下表列出了一些通用功能您可以在自己的类中覆盖 :

Sr.No.方法,描述&样品调用
1

__ init __(self [,args ...])

构造函数(带有任何可选参数)

示例调用: obj = className(args)

2

__ del __(self )

析构函数,删除对象

示例致电: del obj

3

__ repr __(self )

可评估字符串表示

示例调用: repr(obj)

4

__ str __(self )

可打印的字符串表示

示例调用: str(obj)

5

__ cmp __(self,x)

对象比较

示例调用: cmp(obj,x)

重载运算符

假设您已经创建了一个Vector类来表示二维向量.使用加号运算符添加它们会发生什么?很可能Python会对你大喊大叫.

但是,您可以在类中定义 __ add __ 方法来执行向量加法,然后加号运算符将表现为per expectation :

示例

#!/usr/bin/python3class 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)


执行上述代码时,会产生以下结果 :

Vector(7,8)


数据隐藏

对象的属性在类定义之外可能可见也可能不可见.您需要使用双下划线前缀命名属性,然后这些属性将不会被外人直接看到.

示例

#!/usr/bin/python3class JustCounter:   __secretCount = 0     def count(self):      self.__secretCount += 1      print (self.__secretCount)counter = JustCounter()counter.count()counter.count()print (counter.__secretCount)


执行上述代码时,会产生以下结果 :

12Traceback (most recent call last):   File "test.py", line 12, in       print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'


Python通过内部更改名称来保护这些成员包括类名.您可以访问 object._className__attrName 等属性.如果您将以下内容替换最后一行,那么它适用于您和减号;

.........................print (counter._JustCounter__secretCount)


执行上述代码时,它会产生以下结果 :

122