13.1 类的定义和使用
python中使用class关键字来定义类。用类似"class classname():"的语句就可以定义一个新式类。下面的代码是一个简单的类定义:
class IncClass(): n=5 print('initialize') def Incn(self,x): return x+self.n
其中 class IncClass(): 定义了一个类;
n=5是一个类数据成员;
print语句是类代码块;
def语句定义了一个类方法,这个方法的第一个参数是一个self,这个参数指代了一个实例,说明这个类方法必须得通过一个实例来调用。
在使用类的时候一般需要进行实例化后再调用类方法和类变量。示例代码如下:
ic=IncClass()print(ic.Incn(5))
这里IncClass()返回类的实例给ic。
ic.Incn(5)则通过实例ic调用了类方法Incn()。
这段代码的运行结果是
initialize10
13.2 类变量以及实例变量
类变量可以通过类和实例来访问,而实例变量则只能通过实例来访问。
下面的代码演示了使用类和实例来访问一个类变量:
class TestVar(): cvar=9 print(TestVar.cvar)tv=TestVar()print(tv.cvar)
这段代码的运行结果是
99
下面的代码演示了使用类和实例访问一个实例变量:
class TestVar(): def setivar(self): self.ivar=3 tv=TestVar()tv.setivar()print(tv.ivar)print(TestVar.ivar)
这段代码的演示结果为:
3Traceback (most recent call last): File "testclass.py", line 64, in print(TestVar.ivar)AttributeError: class TestVar has no attribute 'ivar'
可以看到使用类访问实例变量的时候发生了错误。类的命名空间并不存在这个变量。
如果类和实例都有一个同名变量,那么在实例中对这个变量赋值,会在实例的命名空间中生成自己的变量,赋值不会影响类变量。下面的演示代码就演示了在实例中对类同名变量进行赋值:
class TestVar(): cvar=4 def setvar(self): self.cvar=3 tv=TestVar()tv.setvar()print(tv.cvar)print(TestVar.cvar)
这段代码的运行结果为:
34
可以看到类变量并没有因为实例变量的修改而改变。
不同的实例如果想要共享同一个类变量的话,那么就不能在实例中进行赋值操作,不然会生成一个实例变量来屏蔽掉类变量。最好使用一个可变变量来绕过这个限制。
下面的代码演示了如何用一个dict来辅助进行多实例的共享变量。
class TestVar(): vardict=dict() vardict['cvar']=4 def setvar(self): self.vardict['cvar']=3 tv=TestVar()tv.setvar()print(tv.vardict['cvar'])print(TestVar.vardict['cvar'])
这段代码的运行结果为:
33
也有人通过实例来获得类,从而可以通过实例来访问类变量。演示代码为:
class TestVar(): cvar=4 def setvar(self): self.__class__.cvar=3 tv=TestVar()tv.setvar()print(tv.cvar)print(TestVar.cvar)
这段代码的运行结果为:
33
这种方法似乎不太被提倡,大概长得比较丑。
13.3 静态方法
之前看到的类方法的定义都是需要通过实例进行调用的。在类中也可以定义静态方法,可以不需要实例化就可以调用。有两种方法可以达到这个效果,一个是使用@classmethod修饰符,一个使用@staticmethod修饰符。示例代码如下:
class TestClass(): @classmethod def cm(cls): print("in classmethod "+cls.__name__) @staticmethod def sm(): print("in staticmethod ")TestClass.cm()TestClass.sm()
以上的代码运行结果为:
in classmethod TestClassin staticmethod
classmethod修饰的函数,第一项参数一定要是cls,也就是类。
而staticmethod修饰的函数可以不带参数。
不过如果staticmethod不带任何类和实例,就无法访问类和实例的变量以及方法。所以,这里使用的时候如果需要访问类和实例的命名空间的话,一般也会自行带上各类参数的。
领取专属 10元无门槛券
私享最新 技术干货