方法是使用属性表示法调用的函数。
实例方法
实例方法第一个参数需要为实例本身(self),需要将类实例化后调用,如果使用类直接调用实例方法,需要显式地将实例作为参数传入。
如果通过实例访问方法(类名称空间中定义的函数),则会得到一个特殊对象:绑定方法(也称为实例方法)对象。
调用时,它会将self参数添加到参数列表中。
绑定方法有两个特殊的只读属性:m . self是方法操作的对象,m . func是实现该方法的函数。调用m(arg-1,arg-2,…,arg-n)完全等同于调用m . func (m . self ,arg-1,arg-2,…,arg-n)。
最左侧传入的参数,是实例本身。
class ClassA(object):
def func_a(self):
print('Hello Python')
if __name__ == '__main__':
# 使用实例调用实例方法
ca = ClassA()
ca.func_a()
# 如果使用类直接调用实例方法,需要显式地将实例作为参数传入
ClassA.func_a(ca)
与函数对象一样,绑定的方法对象支持获取任意属性。但是,由于方法属性实际存储在底层函数对象(meth . func)中,因此不允许在绑定方法上设置方法属性。
尝试设置方法属性会导致引发TypeError。要设置方法属性,您需要在底层函数对象上显式设置它:
class C:
def method(self):
pass
c = C()
c.method.__func__.whoami = 'my name is c'
类方法
通常情况,类方法使用@classmethod
装饰器来声明
类方法传入第一个参数为cls
,是类本身。
类方法可以通过类或实例对象直接调用,但不管哪种方式,最左侧参数传入的都是类对象本身。
class ClassA(object):
@classmethod
def func_a(cls):
print(type(cls), cls)
if __name__ == "__main__":
ClassA.func_a()
ca = ClassA()
ca.func_a()
运行结果如下:
如果有类的继承,类方法获得的是派送类对象。
class BaseA(object):
@classmethod
def func_a(cls):
print(type(cls), cls)
class BaseB(object):
pass
class ClassA(BaseA, BaseB):
pass
if __name__ == '__main__':
ClassA.func_a()
ca = ClassA()
ca.func_a()
代码中ClassA继承自BaseA、BaseB,在调用类方法时,虽然类方法是从BaseA继承而来,但是传入func_a的cls函数实际上是ClassA。
所以,在某些时候,需要明确调用类属性时,不要使用类方法传入的cls参数,因为它传入的是类树中最底层的类,不一定符合设计初衷。可以直接通过类名访问类属性。
静态方法
静态方法无需self与cls参数。使用@staticmethod
装饰器来声明。
在调用过程中,无需将类实例化。
class ClassA(object):
@staticmethod
def func_a():
print('Hello Python')
if __name__ == '__main__':
ClassA.func_a()
ca = ClassA()
ca.func_a()
注意:在Python 2 中,如果一个类的方法不需要self参数,必须声明为静态方法,即加上@staticmethod装饰器,从而不带实例调用它。而在Python 3中,如果一个类的方法不需要self参数,不再需要声明为静态方法,但是这样的话只能通过类去调用这个方法,如果使用实例调用这个方法会引发异常。
参考文献
Was this helpful?
0 / 0