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」
'''

 

posted @ 2022-10-29 13:23  yudai  阅读(791)  评论(0编辑  收藏  举报