Python面向对象(类和对象)

摘要:
自从存在以来,Python一直是面向对象的语言。 因此,创建和使用类和对象是非常容易的。 本章将学习如何使用Python面向对象编程。如果您以前没有面向对象(OO)编程的经验,可能需要查阅介绍面向对象(OO)编程课程或至少学习一些有关教程,以便掌握基本概念。下面是面向对象编程(OOP)的一个小介绍,以帮助您快速入门学习 -OOP术语概述类 - 用于定义表示用户定义对象的一组属性的原型。属性是通过点符号访问的数据成员(类变量和实例变量)和方法。类变量 - 由类的所有实例共享的变量。 类变量在类中定
自从存在以来,Python一直是面向对象的语言。 因此,创建和使用类和对象是非常容易的。 本章将学习如何使用Python面向对象编程。

如果您以前没有面向对象(OO)编程的经验,可能需要查阅介绍面向对象(OO)编程课程或至少学习一些有关教程,以便掌握基本概念。

下面是面向对象编程(OOP)的一个小介绍,以帮助您快速入门学习 -

OOP术语概述

  • - 用于定义表示用户定义对象的一组属性的原型。属性是通过点符号访问的数据成员(类变量和实例变量)和方法。

  • 类变量 - 由类的所有实例共享的变量。 类变量在类中定义,但在类的任何方法之外。 类变量不像实例变量那样频繁使用。

  • 数据成员 - 保存与类及其对象相关联的数据的类变量或实例变量。

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

  • 实例变量 - 在方法中定义并仅属于类的当前实例的变量。

  • 继承 - 将类的特征传递给从其派生的其他类。

  • 实例 - 某个类的单个对象。 例如,对象obj属于Circle类,它是Circle类的实例。

  • 实例化 - 创建类的实例。

  • 方法 - 在类定义中定义的一种特殊类型的函数。

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

  • 运算符重载 - 将多个函数分配给特定的运算符。

1.创建类

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

class ClassName:   'Optional class documentation string'
   class_suitePython
  • 该类有一个文档字符串,可以通过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.salaryPython
  • 变量empCount是一个类变量,其值在此类中的所有实例之间共享。 这可以从类或类之外的Employee.empCount访问。

  • 第一个方法__init __()是一种特殊的方法,当创建此类的新实例时,该方法称为Python构造函数或初始化方法。

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

2.创建实例对象

要创建类的实例,可以使用类名调用该类,并传递其__init__方法接受的任何参数。

## This would create first object of Employee classemp1 = Employee("Maxsu", 2000)## This would create second object of Employee classemp2 = Employee("Kobe", 5000)Python

3.访问属性

可以使用带有对象的点(.)运算符来访问对象的属性。 类变量将使用类名访问如下 -

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

现在把所有的概念放在一起 -

#!/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("Maxsu", 2000)#This would create second object of Employee class"emp2 = Employee("Kobe", 5000)emp1.displayEmployee()emp2.displayEmployee()print ("Total Employee %d" % Employee.empCount)Python

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

Name :  Maxsu ,Salary:  2000Name :  Kobe ,Salary:  5000Total Employee 2Python

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

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

如果不是使用普通语句访问属性,可以使用以下函数 -

  • 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

3.内置类属性

每个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("Maxsu", 2000)emp2 = Employee("Bryant", 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__ )Python

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

Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)Employee.__dict__: {   'displayCount': <function Employee.displayCount at 0x0160D2B8>, 
   '__module__': '__main__', '__doc__': 'Common base class for all employees', 
   'empCount': 2, '__init__': 
   <function Employee.__init__ at 0x0124F810>, 'displayEmployee': 
   <function Employee.displayEmployee at 0x0160D300>,   '__weakref__': 
   <attribute '__weakref__' of 'Employee' objects>, '__dict__': 
   <attribute '__dict__' of 'Employee' objects>}Python

4.销毁对象(垃圾收集)

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>Python

通常情况下,垃圾回收器会销毁孤立的实例并回收其空间。 但是,类可以实现调用析构函数的特殊方法__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 = pt1
pt3 = pt1print (id(pt1), id(pt2), id(pt3));   # prints the ids of the obejctsdel pt1del pt2del pt3Python

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

3083401324 3083401324 3083401324Point destroyedPython

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

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

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

5.类继承

使用类继承不用从头开始构建代码,可以通过在新类名后面的括号中列出父类来从一个预先存在的类派生它来创建一个类。

子类继承其父类的属性,可以像子类中一样定义和使用它们。子类也可以从父类代替代数据成员和方法。

语法

派生类被声明为很像它们的父类; 然而,继承的基类的列表在类名之后给出 -

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

示例

#!/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 methodPython

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

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200Python

以类似的方式,可以从多个父类来构建一个新的类,如下所示:

class A:        # define your class A.....class B:         # define your calss B.....class C(A, B):   # subclass of A and B.....Python

可以使用issubclass()isinstance()函数来检查两个类和实例之间的关系。

  • issubclass(sub,sup)布尔函数如果给定的子类sub确实是超类sup的子类返回True

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

重载方法

可以随时重载父类的方法。 重载父方法的一个原因是:您可能希望在子类中使用特殊或不同的方法功能。

示例

#!/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 methodPython

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

Calling child methodPython

基本重载方法

下表列出了可以在自己的类中覆盖的一些通用方法 -

编号方法描述调用示例
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)

6.重载运算符

假设已经创建了一个Vector类来表示二维向量。当使用加号(+)运算符执行运算时,它们会发生什么? 很可能Python理解不了你想要做什么。

但是,可以在类中定义__add__方法来执行向量加法,然后将按照期望行为那样执行加法运算 -

示例

#!/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)Python

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

Vector(7,8)Python

7.数据隐藏

对象的属性在类定义之外可能或不可见。需要使用双下划线前缀命名属性,然后这些属性将不会直接对外部可见。

示例

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

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

1
2
Traceback (most recent call last):
   File "test.py", line 12, in <module>
      print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'Shell

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

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

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

1
2
2Shell

免责声明:文章转载自《Python面向对象(类和对象)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇mui-——picker使用示例ffmpeg文档22-混合器(复用器)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

处理 EF 并发其实就这么简单

    最近项目有点闲,终于可以了解点自己想了解的了,以前听同事讲面试的经历总会被问到“如何处理高并发大数据” 乍一听感觉这东西好像很有学问的样子,于是并发这个词在脑海里留深刻印像,而且在自己心中的技术地位也提高很多,也导致了解并发相关的知识时,也带着思想负担,总以为很难懂,程序员或许都是这样,在自己不懂的技术领域,别人说一个很简单的技术,给他的感觉都是很...

线程同步以及AutoResetEvent

近期在重构老项目时发现有些地方用了AutoResetEvent,于是查了些资料学习整理。 线程同步介绍 即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多,临界区对象就是其中一种。 同步就是协同步调,按预定的先后次序进行运行。如...

JS-鼠标、键盘事件及事件对象/event

事件对象/event event包含了发生事件的所有信息内容,不如:发生事件类型,发生事件的元素,键盘按下状态等等 事件对象的创建,当事件发生时,游浏览器帮我们创建的,并通过参数的形式传递给事件处理程序的 事件获取方式 //IE window.event; ​ //非IE arguments[0]; //事件处理程序的参数,第一个参数默...

Android优化总结

极力推荐文章:欢迎收藏Android 干货分享 文章转载网络 原文地址如下:https://juejin.im/post/5d072dbc51882540b7104709 1.OOM和崩溃优化 1.2 ANR优化 ANR的产生需要满足三个条件 主线程:只有应用程序进程的主线程响应超时才会产生ANR; 超时时间:产生ANR的上下文不同,超时时间也会...

[TimLinux] JavaScript BOM浏览器对象模型

1. 简介 ECMAScript是JavaScript的核心,但是如果要在WEB中使用JavaScript,那么BOM则无疑才是真的的核心。BOM提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。BOM没有标准,各浏览器厂商间定义的公共对象,可以作为事实上的标准存在。W3C在HTML5中把BOM纳入了规范中。 2. window对象 win...

.NET Mocking Framework对比

  单元测试中,为了让单元测试程序完全脱离外部依赖,需要使用到Mock对象和Stub对象。虽然可以手工编写Mock对象和Stub对象,但通常我们都使用Mocking Framework来帮助我们简单快速的构建需要的Mock对象以及Stub对象。 一、概述   常见的Mocking Framework有如下几种:     1、Rhino Mocks V3...