【Python那些事】 python中类的使用
参考来源
https://www.runoob.com/python/python-object.html
部分术语含义
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。(每个实例共享)
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。(每个实例单独拥有)
- 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
- 方法:类中定义的函数。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)“关系(例图,Dog是一个Animal)。
python创建类
class ClassName:
'类文档字符串'
类体
类文档字符串可以通过下面命令查看:
ClassName.__doc__
类体由类成员,方法,数据属性组成
举个例子:
# -*- coding: UTF-8 -*-
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 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用Employee.empCount 访问。
- 第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
- self 代表类的实例,self 在定义类的方法时是必须有的,在调用时不必传入相应的参数。类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,按照惯例它的名称是 self。
- 什么是内部类、什么是外部类
定义在其他类中的类就是内部类,内部类的外面一层就是外部类。
python创建实例对象
python中类的实例化类似函数调用方式,以下使用类的名称 Employee 来实例化,并通过 __init__方法接收参数。
//创建 Employee 类的第一个对象
emp1 = Employee("Zara", 2000)
//创建 Employee 类的第二个对象
emp2 = Employee("Manni", 5000)
访问属性
python使用点号.来访问类的属性
完整举例:
# -*- coding: UTF-8 -*-
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
还可以添加、修改、删除类的属性:
# -*- coding: UTF-8 -*-
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)
emp1.age = 7
//给对象emp1添加属性age,赋值为7
print(emp1.age)
emp1.age = 8
//更改对象emp1属性age为8
print(emp1.age)
del emp1.age
//删除对象emp1属性age
if hasattr(emp1, 'age') is True:
//hasatter(obj, name) 检查对象obj是否存在一个属性name,存在则返回True
print(getattr(emp1, 'age'))
//getattr(obj, name)返回对象obj中属性name的值,如果属性name不存在则报错
else:
print("No")
setattr(emp1, 'age', 8)
//setattr(obj,name,value) : 设置一个属性name为值value。如果属性不存在,会创建一个新属性。
if hasattr(emp1, 'age') is True:
print(getattr(emp1, 'age'))
else:
print("No")
if hasattr(emp2, 'age') is True:
print(getattr(emp2, 'age'))
else:
print("No")
delattr(emp1, 'age')
//delattr(obj, name) : 删除属性name,若属性不存在则报错
程序运行结果如下:
Name : Zara , Salary: 2000
Name : Manni , Salary: 5000
Total Employee 2
7
8
No
8
No
可见在一个对象里添加属性,不影响另一个对象。
python内置类属性
__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串
__name__: 类名
__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)
python对象销毁(垃圾回收)
python 使用了引用计数这一简单技术来跟踪和回收垃圾。在 python 内部记录着所有使用中的对象各有多少引用。一个内部跟踪变量,称为一个引用计数器。
当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不是"立即"的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
类的继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
在python中继承中的一些特点:
- 如果在子类中需要父类的构造方法就需要显示的调用父类的构造方法,或者不重写父类的构造方法。
- 在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中用普通函数时并不需要带上 self 参数
- python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
举个例子:
# -*- coding: UTF-8 -*-
class Parent:
//定义父类
parentAttr = 100
def __init__(self):
print("调用父类构造函数")
def parentMethod(self):
print('调用父类方法')
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print("父类属性 :", Parent.parentAttr)
class Child(Parent):
//定义子类
def __init__(self):
print("调用子类构造方法")
def childMethod(self):
print('调用子类方法')
c = Child()
//实例化子类
c.childMethod()
//调用子类的方法
c.parentMethod()
//调用父类方法
c.setAttr(200)
//再次调用父类的方法 - 设置属性值
c.getAttr()
//再次调用父类的方法 - 获取属性值
程序运行结果如下:
调用子类构造方法
调用子类方法
调用父类方法
父类属性 : 200
python一个子类还可以继承多个父类
class A:
//定义类 A
.....
class B:
//定义类 B
.....
class C(A, B):
//继承类 A 和 B
.....
python 子类继承父类构造函数说明
如果在子类中需要父类的构造方法就需要显式地调用父类的构造方法,或者不重写父类的构造方法。
子类不重写 _ init _,实例化子类时,会自动调用父类定义的 _ init 。
如果重写了 init _ 时,实例化子类,就不会调用父类已经定义的 _ init _。
如果重写了_ init_ 时,要继承父类的构造方法,可以使用 super 关键字
super(子类, self)._ init _(参数1,参数2,…)
或者
父类名称._ init _(self,参数1,参数2,…)
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name))
def getName(self):
return 'Father ' + self.name
class Son(Father):
def __init__(self, name):
super(Son, self).__init__(name)
print ("hi")
self.name = name
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )
或者
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name))
def getName(self):
return 'Father ' + self.name
class Son(Father):
def __init__(self, name):
Father.__init__(self, name)
print ("hi")
self.name = name
def getName(self):
return 'Son '+self.name
if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法
简单的说,就是可以在子类中定义一个和父类中相同名字的方法,这样调用这个方法时,用的是子类中重新定义的,而不是父类中的。
基础重载方法
什么是重载函数:
重载函数是函数的一种特殊情况,为方便使用,python允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是说用同一个函数完成不同的功能。这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。不能只有函数返回值类型不同。
类属性与方法
- 类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。 - 类的方法
在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数 - 类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods
单下划线、双下划线、头尾双下划线说明:
- _ foo _: 定义的是特殊方法,一般是系统定义名字 ,类似 _ init _() 之类的。
- _foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
- __foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
结语
如果您有修改意见或问题,欢迎留言或者通过邮箱和我联系。
手打很辛苦,如果我的文章对您有帮助,转载请注明出处。