类的定义
语法格式:
class 类名(继承类):
(>=0)个类属性...
(>=0)个类方法...
其中类属性指的是包含在类中的变量(对照C++成员),类方法指的是包含在类中的函数(对照C++成员函数),类属性和类方法的顺序可以任意调换
实例:
class MyClass:
'''
自己定义的一个类
'''
# 定义一个类方法
def printInfo(self,info):
print("MyClass:",info)
# 定义一个类属性
defaultInfo="Default Info"
self
在定义类的过程中,无论是显式创建类的构造方法,还是向类中添加实例方法,都要求将 self 参数作为方法的第一个参数。self参数有点类似C++中的this指针。
同一个类可以产生多个实例化对象,当某个对象调用类方法时,该对象会将自身的引用作为第一个参数自动传递到该方法上,如此Python解释器就知道要操作哪个对象的方法了。
>>> class MyClass:
def lookSelf(self):
print(self)
>>> c= MyClass()
>>> c.lookSelf()
<__main__.MyClass object at 0x000002811B94C4F0>
>>> d= c.lookSelf
>>> d()
<__main__.MyClass object at 0x000002811B94C4F0> #同一对象
>>>
类的实例化
实例化后的类对象可以执行以下操作:
访问或修改类对象具有的实例变量,也可以添加新的实例变量或删除旧的实例变量,如果新添的实例变量与类中的方法重名,则会顶替掉类方法
调用类对象的方法,也可以给类对象动态添加方法,若位类对象动态添加方法,需要手动添加self属性将其绑定到第一个参数上
类属性和实例属性
根据变量定义的位置不同以及定义的方式不同,类属性可以分为以下三种:
类属性/类变量:类体中、所有函数之外
实例属性/实例变量:类体中,所有函数内部,且以self.变量名的方式定义的变量
局部变量:类体中,所有函数内部,且以变量名 = 变量值定义的变量
类变量/类属性
对于类属性/类变量,所有类的实例化对象都同时共享类变量,类变量在所有实例化对象中是作为共有资源存在的,可以通过类名.类变量调用,也可以通过实例化对象.类变量调用。因此,通过类名修改类变量会影响所有实例化对象:
>>> class MyClass():
var =10 #类变量
>>> MyClass.var
10
>>> a=MyClass() # 实例化对象a
>>> b=MyClass() # 实例化对象b
>>> a.var
10
>>> b.var
10
>>> a.var=12 # 相当于定义新的实例变量
>>> b.var # 不影响b
10
>>> MyClass.var=15 # 通过类名修改类变量
>>> a.var # a的var现在是新的实例变量
12
>>> b.var # b作为MyClass的实例化对象,受影响
15
>>> #同理,也可以动态地为类和对象添加类变量
实例属性/实例变量
对于实例属性/实例变量,其特点是只作用于调用方法的对象,同时也只能通过对象名访问,无法通过类名访问。上面的例子提到,无法通过类对象修改类变量,本质是新添实例变量
>>> class MyClass():
varA=10
def getVarB(self):
self.varB=20
>>> c=MyClass()
>>> c.varA # 类变量varA
10
>>> c.varB # 实例变量varB
Traceback (most recent call last):
File "", line 1, in
c.varB
AttributeError: 'MyClass' object has no attribute 'varB'
>>> c.getVarB() # 调用getVarB()后才存在varB
>>> c.varB
20
>>>
局部变量
对于局部变量,局部变量直接以“变量名=值”的方式进行定义,局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。
_slots_限定绑定
Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
>>> class Student(object):
__slots__ = ('name','age') # 用tuple定义允许动态绑定的变量名
>>> student = Student()
>>> student.name='A'
>>> student.age=18
>>> student.score=95
Traceback (most recent call last):
File "", line 1, in
student.score=95
AttributeError: 'Student' object has no attribute 'score'
>>>
实例方法、静态方法和类方法
类方法可以区分为实例方法、静态方法和类方法,采用@classmethod修饰的方法就是类方法,采用@staticmethod修饰的就是静态方法,不使用任何修饰的就是实例方法。
实例方法
通常情况下,Python中的方法默认都是实例方法,实例方法最少需要一个self参数,用于绑定调用此方法的实例对象,实例方法可以由实例对象直接调用(不需要显示传入self参数),也可以用类名调用实例方法,但需要手动传入self参数:
>>> MyClass.getVarB(c)
>>> class MyClass():
def MyMethod(self):
print("调用MyMethod()")
>>> c=MyClass()
>>> c.MyMethod()
调用MyMethod()
>>> MyClass.MyMethod(c) #手动传参
调用MyMethod()
>>>
类方法
类方法与实例方法类似,都需要至少一个参数,通常命名为cls而不是self(习惯问题),Python会自动将类本身绑定给cls参数,利用类名调用类方法时,无需显示地为cls传参。
>>> class MyClass():
@classmethod
def MyClassMethod(cls):
print("调用MyClassMehod()")
>>> MyClass.MyClassMethod() # 无需显式传参
调用MyClassMehod()
>>> c=MyClass
>>> c.MyClassMethod() # 也可以利用实例化对象调用,但是不推荐
调用MyClassMehod()
>>>
静态方法
静态方法实际上就是定义在类内部的函数,与函数的区别就是静态方法定义在类命名空间中,而普通的函数定义在全局命名空间中。静态方法采用关键字@staticmethod
由于静态方法无需self 或 cls 参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定,即类的静态方法无法调用任何类方法和类属性。静态方法的调用既可以使用类名,也可以使用类对象。
在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能,但是在工厂模式中时不错的选择。