Python - 类和对象
Python 是一种 面向对象编程语言,这意味着它基于 OOP 概念的原则。Python 程序中使用的实体是一个或另一个 class 的 object。例如,数字、字符串、列表、字典以及程序中的其他类似实体都是相应内置 class 的对象。
在 Python 中,名为 Object 的 class 是所有 class 的基类或父类,包括内置的和用户定义的。
Python 中的 Class 是什么?
在 Python 中,class 是用户定义的实体(数据类型),它定义了 object 可以包含的数据类型及其可以执行的操作。它用作创建对象的模板。例如,如果我们想在 Python 程序中为智能手机定义一个 class,我们可以使用像 RAM、ROM、屏幕尺寸这样的数据类型,以及拨打电话和发送消息这样的操作。
在 Python 中创建 Class
使用 class 关键字在 Python 中创建新 class。class 的名称紧跟在 class 关键字后面,后跟冒号,如下所示 −
class ClassName: 'Optional class documentation string' class_suite
class 有一个文档字符串,可以通过 ClassName.__doc__ 访问。
class_suite 包含定义 class 成员、数据属性和函数的所有组件语句。
示例
以下是一个简单的 Python class 示例 −
class Employee:
'所有员工的通用基类'
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 是 class 变量,其值在该 class 的所有实例之间共享。可以从 class 内部或外部通过 Employee.empCount 访问。
第一个方法 __init__() 是一个特殊方法,被称为 class 构造函数或初始化方法,当你创建该 class 的新实例时,Python 会调用它。
你像声明普通函数一样声明其他 class 方法,只是每个方法的第一个参数是 self。Python 会为你将 self 参数添加到列表中;调用方法时无需包含它。
什么是 Object?
object 指的是给定 Python class 的一个实例。每个 object 都有由其 class 定义的属性和方法。
创建 class 时,它仅描述了 object 的结构。当从 class 实例化 object 时,才会分配内存。
在上图中,Vehicle 是 class 名称,Car、Bus 和 SUV 是它的对象。
在 Python 中创建 Class 的 Object
要创建 class 的实例,使用 class 名称调用 class,并传入其 __init__ 方法接受的任何参数。
# 这将创建 Employee class 的第一个对象
emp1 = Employee("Zara", 2000)
# 这将创建 Employee class 的第二个对象
emp2 = Employee("Manni", 5000)
Python 中访问对象属性
你可以使用点运算符通过对象来访问对象的属性。类变量将使用类名来访问,如下所示 −
emp1.displayEmployee()
emp2.displayEmployee()
print ("Total Employee %d" % Employee.empCount)
现在,将所有概念放在一起 −
class Employee:
"所有员工的通用基类"
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)
# 这将创建 Employee 类的第一个对象
emp1 = Employee("Zara", 2000)
# 这将创建 Employee 类的第二个对象
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print ("Total Employee %d" % Employee.empCount)
执行上述代码时,将产生以下结果 −
Name : Zara , Salary: 2000 Name : Manni , Salary: 5000 Total Employee 2
你可以在任何时候添加、删除或修改类和对象的属性 −
# 添加 'age' 属性 emp1.age = 7 # 修改 'age' 属性 emp1.age = 8 # 删除 'age' 属性 del emp1.age
除了使用普通语句访问属性外,你还可以使用以下函数 −
getattr(obj, name[, default]) − 用于访问对象的属性。
hasattr(obj,name) − 用于检查属性是否存在。
setattr(obj,name,value) − 用于设置属性。如果属性不存在,则会创建它。
delattr(obj, name) − 用于删除属性。
# 如果 'age' 属性存在则返回 True hasattr(emp1, 'age') # 返回 'age' 属性的值 getattr(emp1, 'age') # 将属性 'age' 设置为 8 setattr(emp1, 'age', 8) # 删除属性 'age' delattr(empl, 'age')
Python 中的内置类属性
每个 Python 类都保持以下内置属性,它们可以使用点运算符像其他属性一样访问 −
| SNo. | Attributes & Description |
|---|---|
| 1 | __dict__
包含类命名空间的字典。 |
| 2 | __doc__
类文档字符串,如果未定义则为 None。 |
| 3 | __name__
类名 |
| 4 | __module__
定义类的模块名称。在交互模式下,此属性为 "__main__"。 |
| 5 | __bases__
一个可能为空的元组,包含基类,按照它们在基类列表中的出现顺序。 |
示例
对于上述 Employee 类,让我们尝试访问其属性 −
class Employee:
'所有员工的通用基类'
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__)
执行上述代码时,将产生以下结果 −
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 遵循面向对象编程范式。字符串、列表和数据类型等实体都属于某个内置 class。
如果我们想查看哪种数据类型属于哪个内置 class,可以使用 Python 的 type() function。这个 function 接受一个数据类型并返回其对应的 class。
示例
下面的示例演示了如何检查给定数据类型的内置 class。
num = 20
print (type(num))
num1 = 55.50
print (type(num1))
s = ""
print (type(s))
dct = {'a':1,'b':2,'c':3}
print (type(dct))
def SayHello():
print ("Hello World")
return
print (type(SayHello))
执行这段代码时,它将显示 Python 数据类型的对应 class −
<class 'int'> <class 'float'> <class 'str'> <class 'dict'> <class 'function'>
Python 中的垃圾回收(销毁对象)
Python 会自动删除不需要的对象(内置类型或 class 实例)以释放内存空间。Python 定期回收不再使用的内存块的过程称为 Garbage Collection。
Python 的垃圾回收器在程序执行期间运行,当对象的引用计数达到零时触发。对象的引用计数会随着指向它的别名数量的变化而变化。
当对象被赋予新名称或放入容器(list、tuple 或 dictionary)中时,其引用计数增加。当使用 del 删除它、其引用被重新赋值或其引用超出作用域时,引用计数减少。当对象的引用计数达到零时,Python 会自动收集它。
# 创建对象 <40> a = 40 # 增加 <40> 的引用计数 b = a # 增加 <40> 的引用计数 c = [b] # 减少 <40> 的引用计数 del a # 减少 <40> 的引用计数 b = 100 # 减少 <40> 的引用计数 c[0] = -1
通常你不会注意到垃圾回收器何时销毁未使用的实例并回收其空间。但一个 class 可以实现特殊方法 __del__(),称为 destructor,当实例即将被销毁时调用。该方法可用于清理实例使用的非内存资源。
示例
__del__() destructor 会打印即将被销毁的实例的 class 名称,如下面的代码块所示 −
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
# 打印对象的 id
print (id(pt1), id(pt2), id(pt3))
del pt1
del pt2
del pt3
执行后,上述代码将产生以下结果 −
135007479444176 135007479444176 135007479444176 Point destroyed
Python 中的数据隐藏
对象的属性在 class 定义外部可能可见也可能不可见。你需要为属性命名时使用双下划线前缀,这样这些属性就不会直接对外部可见。
示例
class JustCounter:
__secretCount = 0
def count(self):
self.__secretCount += 1
print self.__secretCount
counter = JustCounter()
counter.count()
counter.count()
print counter.__secretCount
执行上述代码时,会产生以下结果 −
1 2 ERROR! Traceback (most recent call last): File <main.py>", line 11, in <module> AttributeError: 'JustCounter' object has no attribute '__secretCount'
Python 通过在内部将名称更改为包含 class 名称的方式保护这些成员。你可以以 object._className__attrName 的形式访问此类属性。如果你将最后一行替换为以下内容,它就会正常工作 −
print(counter._JustCounter__secretCount)
执行上述代码时,会产生以下结果 −
1 2 2