定义:使用装饰器@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」