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