Python 实例方法、类方法、静态方法之间的区别及实例说明
类方法
-
定义:使用装饰器@classmethod。第一个参数为“cls”(也可为self),通过它来传递类的属性和方法(不能传实例的属性和方法,即使第一个参数为self,传递的也是类的属性和方法)
- 被调用:类和实例对象都可以调用类方法,不用传对象名
类名.类方法名(args)
实例名.类方法名(args)
实例方法
-
定义:第一个参数为“self”,通过它来传递实例的属性和方法
传递实例属性和方法调用方式”实例名.实例方法名(args)”,这里参数里不包含对象self或cls
传递类属性和方法调用方式为”类名.实例方法名(类名|实例名, args)”,参数包含对象self或cls
-
被调用:实例和类都能调用(只能由实例对象调用实例方法)
如果实例对象调用时 在参数不传对象,写法为 实例名.实例方法名(args)
如果类对象调用时 在参数里传入对象,写法为 类名.实例方法名(类名|实例名, args)
静态方法
-
定义:使用装饰器@staticmethod。参数可有可无,“self”和“cls”均表示传入的对象;
A)静态方法里不能调用实例属性;
B)可调用类属性,但是方法体中不能使直接使用类或实例的任何属性和方法(可以通过类名来调用,例如 “类名.属性”;)
- 被调用:类和实例对象都可以调用静态方法,跟实例方法调用相同
self和cls 的区别:self是类(Class)实例化对象,cls就是类(或子类)本身,取决于调用的是哪个类。
实例方法调用方式:实例函数需要将实例化对象或者类名称传入 self 对象
实例名.实例方法名(args)
类名.实例方法名(实例名,args)
类名.实例方法名(类名,args)
类名.实例方法名(xx, args) 传入的对象如果为实例对象,则类方法里调用的self.a 或 cls.a为实例变量,无实例变量则用类变量;传入的对象为 类对象,self.a 或cls.a为类变量,没有类变量会报错。
# 实例方法的三种调用方式 class A(object): # 无实例变量,有类变量 a = 'a' def instanceMethod_A(self, name): print('hello', name, self.a) # 如果传入的对象为实例,因为无实例变量,所以self.a为 类变量
class B(object): # 有实例变量,有类变量 a = "b" def __init__(self,b): self.a = b def instanceMethod_B(self, name): print('hello', name, self.a) # 如果传入的对象实例,因为有实例变量,self.a 为实例变量
class C(object): # 无类变量,有实例变量 '''通过 "类.实例方法名(类, "args")" 来调用实例时,会报错没有类属性错误''' # a = "b" def __init__(self,b): self.a = b def instanceMethod_C(self, name): print('hello', name, self.a) # 这里self.a 需根据传入的对象是类 还是 实例决定,如果传入的是类,由于没有类变量,则会报错
a = A() b = B("bb")
a.instanceMethod_A("小熊猫") # hello 小熊猫 # 总结:传入self 的对象为实例a,所以self.a表示实例的变量;如果有实例变量就用实例变量,如果没有实例变量a,就会用类变量 A.instanceMethod_A(a,"小熊猫") # 传入对象为实例,由于无实例变量,self.a 为类变量。 B.instanceMethod_B(b,"小熊猫") # 传入对象为实例,由于有实例变量,self.a 为实例变量 A.instanceMethod_A(A,"小熊猫") # 传入self 的对象为类A,所以self.a表示类变量;如果没有类变量a 则会报错 C.instanceMethod_C(C,"小熊猫") # 传入self 的对象为类C,self.a表示类变量;由于没有类变量a,报错 # hello 小熊猫 a # hello 小熊猫 a # hello 小熊猫 bb # hello 小熊猫 a # 报错
类方法调用方式:参数中 无需传“类对象”或者“实例对象”
类名.类方法名(args)
实例名.类方法名(args)
【类方法的第一个参数为 cls和self 的区别】类方法里只能调用类变量,不能调用实例变量,所以示例中调用的self.name 和 cls.name都表示类变量
# 类方法的调用:参数中不用传递对象,通过类名或对象名调用 class Dog(object): name='SB' #类变量 def __init__(self,name): self.name=name @classmethod #类方法只能访问类变量,不能访问实例变量;这里self.name表示类变量 def eat1(self,name): print('%s is eating %s'%(self.name,name)) # self.name 是类变量 @classmethod #类方法只能访问类变量,不能访问实例变量;这里cls.name表示类变量 def eat2(cls,name): print('%s is eating %s'%(cls.name,name)) # cls.name 是类变量 d=Dog('Lulu') d.eat1('Mantou1') # 参数是self,传输的对象是实例d d.eat2('Mantou2') # 参数是cls,传输的对象是实例d Dog.eat1("Mantou3") # 参数是self,传输的对象是类D Dog.eat1("Mantou4") # 参数是cls,传输的对象是类D d.talk("nothing") ''' >>>>>> SB is eating Mantou1 SB is eating Mantou2 SB is eating Mantou3 SB is eating Mantou4 Lulu is talking nothing '''
静态方法调用方式:如果传入对象,则属性根据传入对象决定
实例名.静态方法名(args) 或 实例名.静态方法名(objectName, args)
类名.静态方法名(args) 或 类名.静态方法名(objectName, args)
【说明】类名.静态方法名(objectName, args) 传入的对象如果为实例对象,则类方法里调用的self.a 或 cls.a 为实例变量,无实例变量则用类变量;传入的对象为 类对象,self.a 或 cls.a 为类变量,没有类变量会报错。
# 静态方法调用 class A(object): # 无类变量,有实例变量 # a = '「调用类属性a」' def __init__(self): self.a = "「调用实例属性a」" @staticmethod def hasObjectSelf(self,name): print('hello', name, self.a) # self.a 根据传入对象决定,传入类,则为类属性,传入实例,则为实例属性; @staticmethod def hasObjectCls(cls, name): print('hello', name, cls.a) # cls.a 根据传入对象决定,传入类,则为类属性,传入实例,则为实例属性; class B(object): # 有类变量,无实例变量 b = '「调用类属性b」' @staticmethod def noObject(name): print('hello', name, B.b) # 调用类属性需要通过 “类名.属性名” @staticmethod def hasObjectSelf(self,name): # self print('hello', name, B.b, self.b) # self.a 根据传入对象决定,传入类,则为类属性,传入实例,则为实例属性; @staticmethod def hasObjectCls(cls, name): print('hello', name, B.b, cls.b) # cls.a 根据传入对象决定,传入类,则为类属性,传入实例,则为实例属性; a = A() b = B() # 不用传入对象,实例和类分别调用静态方法 b.noObject("小熊猫") # hello 小熊猫 「调用类属性b」 B.noObject("小熊猫") # hello 小熊猫 「调用类属性b」 # 需传入对象,传入对象分别为实例和类 a.hasObjectSelf(a, "小熊猫aa") # 传入的对象为实例,由于有实例,则self.a为实例属性 # a.hasObjectSelf(A, "小熊猫aa") # 传入的对象为类变量,由于没有类,报错 # 需传入对象,传入对象分别为实例和类 A.hasObjectCls(a, "小熊猫aa") # 传入的对象为实例,由于有实例,则self.a为实例属性 # A.hasObjectCls(A, "小熊猫aa") # 传入的对象为类,由于没有类变量,报错 # 需传入对象,传入对象分别为实例和类 B.hasObjectSelf(b, "小熊猫bb") # 传入的对象为实例,由于没有实例,则self.a为类属性 B.hasObjectSelf(B, "小熊猫bb") # 传入的对象为类,则self.a为类属性 ''' hello 小熊猫 「调用类属性b」 hello 小熊猫 「调用类属性b」 hello 小熊猫aa 「调用实例属性a」 hello 小熊猫aa 「调用实例属性a」 hello 小熊猫bb 「调用类属性b」 「调用类属性b」 hello 小熊猫bb 「调用类属性b」 「调用类属性b」 '''