类属性只有类及其实例能够访问,可以理解为一个独立的命名空间。
Python中类属性的引用方式有两种:
1. 通过类的实例进行属性引用,称为绑定方法(bound method),可以理解为方法与实例绑定在一起。
2. 通过类进行属性引用,称为非绑定方法(unbound method),方法没有与实例绑定。
在绑定方法中,为了与实例绑定,Python自动将实例作为方法的第一个参数,而非绑定方法则表现的像普通函数,和普通函数的区别在于它只能通过类来访问。
两种引用方式:
1 class A: 2 def test1(self): 3 print(self) 4 5 def main(): 6 a = A() 7 a.test1() 8 A.test1(a) 9 A.test1(2) 10 11 if __name__ == "__main__": 12 main()
输出结果:
1 <__main__.A object at 0x00000212C48D5908> 2 <__main__.A object at 0x00000212C48D5908> 3 2
上述代码中,类A有一个test1方法。两种引用方式说明如下:
1. 通过实例a来引用方法时,python自动将a作为第一个参数(self)传给方法test1。
2. 通过类来直接引用时,需要显式传给test1一个self参数,但是这个参数并不要求一定要是类的实例,传入其他值亦可(上述代码中传入的是2)。
引用方式的问题与优点:
1 class A: 2 def test2(): 3 print("hello") 4 5 def test3(solf): 6 print(solf) 7 8 class B: 9 pass 10 11 def main(): 12 a = A() 13 try: 14 a.test2() 15 except Exception as e: 16 print(e) 17 b = B() 18 A.test3(b) 19 20 if __name__ == "__main__": 21 main()
输出结果:
1 test2() takes 0 positional arguments but 1 was given 2 <__main__.B object at 0x000001DFE1AC7898>
由于实例引用会隐式传入实例作为方法的第一个参数,所以当类的方法不接受参数的时候,使用实例就无法调用该方法。
类引用的显式传参没有要求,所以可以将A类的方法作用于B上。
类方法(classmethod)和静态方法(staticmethod):
1 class A: 2 @classmethod 3 def test4(self): 4 print(f"classmethod: {self}") 5 6 @staticmethod 7 def test5(self): 8 print(f"staticmethod: {self}") 9 10 def main(): 11 a = A() 12 a.test4() 13 A.test4() 14 a.test5(2) 15 A.test5(2) 16 17 18 if __name__ == "__main__": 19 main()
输出结果:
classmethod: <class ‘__main__.A‘> classmethod: <class ‘__main__.A‘> staticmethod: 2 staticmethod: 2
类方法和静态方法使用装饰器实现,和普通的方法有所区别。
从作用上看:
1. 类方法是只与类相关,而与类的实例无关的方法。
2. 静态方法是与类和实例都无关的方法。
从实现上看:
1. 类方法和静态方法统一了实例引用和类引用,两者都能通过两种引用方式调用。
2. 类方法永远隐式地使第一个传入的参数为类,静态方法所有参数都需要显示传入。
总结:
1. 类属性引用有两种,分为实例引用和类引用,对于方法属性,前者隐式传入实例作为第一个参数,后者类似于普通函数
2. self和cls是约定的实例和类的名称表示,并无强制性含义,类引用时可以传入任意值而不一定是类实例
3. 类方法与静态方法统一了两种引用方式,前者永远隐式传入类作为第一个参数,后者所有参数都需要显示传入。
原文地址:https://www.cnblogs.com/luoheng23/p/10989572.html