8.1.2 属性与方法
1.类属性
属性用于描述事物的特征,如颜色、大小、数量等。属性可以分为类属性和对象属性。
类的属性存储了类的各种数据,定义在类的内部、方法的外部,由该类所有的对象共同拥有。类属性可以通过类名访问,也可以通过对象名访问,但只能通过类名修改。
属性调用格式:
如给冰箱类定义两个属性:冰箱编号、物品编号。代码如下:
2.对象属性
对象属性是对象特征的描述,定义非常灵活,可在方法内部定义,也可在调用实例时动态添加。
在对象方法里可以使用self关键字定义和访问对象属性,同名的对象属性会覆盖类属性。在类中定义的方法经常需要有自己需要的参数,这类参数称为对象属性,可以在方法中定义,也可以调用时定义。在方法中定义时以self作前缀,且只能通过对象名访问。如给冰箱类定义一个对象属性(物品名称),在调用时添加一个新属性num,代码如下:
运行结果如下:
上面的代码中,先创建了一个对象fridge1,再通过属性赋值设置Num的值为4,在调用时,通过对象fridge1调用了方法pack(),并传入“大象”给对象属性goods,而对象fridge2创建后直接调用方法pack()。从运行结果看fridge1修改的Num值仅对当前对象本身有效,对其他对象无效,因此对象fridge2调用时,重新编号。
由此可知对象和类都可访问类属性的值,但是对象不能修改类属性的值,可以通过定义与类属性同名的属性,覆盖类属性。
对象属性可动态创建,也可动态删除,使用语句:
例如,删除上面冰箱对象fridge1的Num属性:
输出结果将会是0。如果类属性中并无相应同名属性,会因为无法访问相应属性,而导致解释器发生异常,运行结果将会报错。
3.对象方法
对象方法也称为实例方法,是在类中定义的,以关键字self作为第一个参数的方法。对象方法的self参数代表调用这个方法的对象本身,在方法调用时,可以不用传递这个参数,系统会自动将调用方法的对象作为self参数传入。
类中定义的方法必须有一个参数self,位于参数列表的开头,代表类的实例(即对象自身)。在内部可以使用self调用类的属性和成员函数。在外部则使用对象名来调用对象方法,且不需要传递这个参数。如果在外部通过类名来调用对象方法,则需要显式为self传值。
上面代码中的pack(self,goods)为对象方法,调用时,无须为self传递参数。
对象方法是属于对象的方法,对象可以直接调用,但是类不可以直接调用对象方法,如果类想要调用对象方法,需要将类或者该类的对象作为参数传递给self。代码如下:
4.构造方法和析构方法
在类的方法中,有两种特殊的方法,分别在类创建时和销毁时自动调用,它们是构造方法__init__()和析构方法__del__()。
使用“类名()”可以创建对象,但实际上,每次创建对象后,系统会自动调用__init__()方法。每个类都有一个默认的构造方法,如果在自定义类时显示定义了,则创建对象时调用定义的__init__()。
__init__()方法的第一个参数是self,即代表对象本身,不需要显示传递实参。但是在创建类时传入的参数实际上都传递给了__init__()。如将冰箱开门的动作设为自动的,只要创建冰箱自动就会调用开门,代码如下:
运行结果如下:
在创建对象时,系统会自动调用__init__()方法,在对象被清除的时候,系统则会自动调用析构方法__del__()。
__del__()的使用说明如下。
·函数名和参数:Python解释器内部约定,保留方法。
·调用条件:当实例对象被真实删除时,才调用该函数内语句。
·真实删除:当前对象的引用数为0或当前程序退出(垃圾回收)。
清除对象使用del语句,del语句可以删除对象的一个引用,代码如下:
运行结果如下:
5.类方法
类方法是使用修饰器@classmethod修饰的方法,由所有实例对象共享,可以对外提供简单易用的接口。它以cls作为第一个参数,代表类本身,在调用时,不需要传递这个参数,系统会自动将调用它的类作为参数传入。
类方法可以对类属性进行修改。类方法只能操作类属性和其他类方法,不能操作实例属性和实例方法。
通过前面对象方法的知识,我们知道,在对象方法中无法给类属性赋值,在对象方法中对类属性赋值相当于动态创建一个同名的对象属性。下面的代码分别使用对象方法和类方法来对类属性进行操作:
运行结果如下:
从运行结果可以看出,调用了对象方法add_No1()后,类属性No的值并没有改变,因为对象方法中的代码“self.No+=1”实际上创建了一个同名的对象属性,并不是改变类属性的值。而调用了add_No2()后,通过语句“cls.No+=1”,类属性No的值才是真正被修改为1了。
Python是一种很灵活的语言,对于类方法的调用也是相当灵活的,可以由类调用类方法,也可以由对象调用类方法。但是当用对象调用类方法时,系统会自动将对象所属的类作为第一个默认参数传递给类方法的cls。
类方法可以与对象方法进行转换,通过使用内置函数classmethod()的方式将一个普通的方法转换为类方法。如语句“p_to_class=classmethod(add_No)”就能将对象方法add_No1()转换为类方法。
6.静态方法
静态方法是使用装饰器@staticmethod进行修饰的方法,它不需要传入默认参数,所以与类并没有很强的联系。也正是因为没有传入默认参数,所以在静态方法中不能直接访问类的属性和方法,需要通过<类名.方法名>或<类名.属性名>的方式来访问。
静态方法相当于面向过程中定义的函数,适合进行与类无关的操作,不需要在方法内使用类的相关数据。比如一些工具类,只需要根据传入的参数进行操作即可。
静态方法与类方法的区别:
·类方法有cls参数,而静态方法没有;
·类方法可以根据传入的参数访问类的数据,静态方法不可以;
·静态方法不经过实例化就可以直接使用;
·静态方法和静态变量属于某一个类,而不属于类的对象。
对象方法、类方法和静态方法的特征归纳如表8-1所示。
表8-1 对象方法、类方法和静态方法的特征