面向对象
文章目录
面向对象编程的好处就是让程序更能清晰的表达出其含义,类丰富了语言的自定义数据类型以及含义,另外,面向对象编程更容易系统的维护和扩展。因为类把相同的内容封装起来,一旦需要修改或扩展,是比较聚焦的。
类被经常运用在Tensorflow和Keras等深度学习框架的自定义网络层中,而Pytorch的神经网络搭建更是需要用到类的创建和继承。
创建类
class ClassName:
'类的帮助信息' #可通过ClassName.__doc__查看
class_suite #由类成员、方法、数据属性组成
class Employee:
empCount = 0 #一个类变量,它的值将在所有实例之间共享,可以在内部类或外部类使用Employee.empCount访问
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)
emp1.displayEmployee()
第一种方法__ init__()被称为类的构造函数或初始化方法,当创建这个类的实例就会调用该方法
self代表类的实例,self在定义类时是必须有的,虽然在调用时不需要传入相应的参数
self代表类的实例,而非类
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
<__main__.Test object at 0x0000000006FD1208>
<class '__main__.Test'>
self代表的是类的实例,代表当前对象的地址,而self.__ class__ 则指向类。
self不是Python关键字,换成其他的(比如roo)也可以正常执行。
创建实例对象
类的实例化类似函数调用方式,使用点号 . 来访问对象的属性
添加、删除、修改类的属性
emp1.age=7 #添加一个‘age’属性
emp1.age=8 #修改‘age’属性
del emp1.age #删除‘age’属性
使用以下函数的方式来访问属性:
- getattr(obj, name[, default]) : 访问对象的属性。
- hasattr(obj,name) : 检查是否存在一个属性。
- setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
- delattr(obj, name) : 删除属性。
Python对象销毁
Python使用引用计数这一简单技术来跟踪和回收垃圾,在Python内部记录着所有使用中的对象各有多少引用
a = 40 # 创建对象 <40>
b = a # 增加引用, <40> 的计数
c = [b] # 增加引用. <40> 的计数
del a # 减少引用 <40> 的计数
b = 100 # 减少引用 <40> 的计数
c[0] = -1 # 减少引用 <40> 的计数
析构函数 __ del__ ,__ del _ 在对象销毁的时候被调用,当对象不再被使用时,_ del__方法运行:
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, "销毁")
pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3)) # 打印对象的id
del pt1
del pt2
del pt3
117326680 117326680 117326680
Point 销毁
类的继承
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
在python中继承中的一些特点:
-
1、如果在子类中需要父类的构造方法就需要显示的调用父类的构造方法,或者不重写父类的构造方法。
-
2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数
-
3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
-
issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
-
isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。
类属性和类方法
类的私有属性
__ private _attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或访问,在类的内部使用 self.__private _attrs
类的方法
在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods
单下划线、双下划线、头尾双下划线说明:
- foo: 定义的是特殊方法,一般是系统定义名字 ,类似 init() 之类的。
- _foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
- __foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了