Python 3语法小记 类class

来源:互联网 发布:windows快捷键设置 编辑:程序博客网 时间:2024/05/17 07:02
Python 3 中只有新式类,没有旧式类,不需要显示的指定,你定义的类都是新式类

如果你不知道新式类和旧式类的区别,那么,也不用知道了


定义:

[python] view plaincopyprint?
  1. >>> class Nothing:  
  2.     #定义方法和属性  
  3.     pass  
  4.   
  5. >>>  


类里面用 def 定义方法,它不叫函数,因为每一个方法的第一个参数都是 self,但在调用时我们不必提供,程序会自动将第一个参数绑定到所属的实例上

[python] view plaincopyprint?
  1. >>> class Hello:  
  2.     def greet(self,name):  
  3.         print ("Hello,"+name)  
  4.   
  5.           
  6. >>> me = Hello() #要加()不然,不是实例  
  7. >>> me.greet('Cheng'#只需第一个参数  
  8. Hello,Cheng  


Python 中默认情况下的方法和特性都是公有的,如果你想变为私有的,那么要在方法和特性的名字前加上双下划线 __ 

[python] view plaincopyprint?
  1. >>> class Some:  
  2.     name = "Jane"  
  3.   
  4.       
  5. >>> she = Some()  
  6. >>> she.name #这里可以访问  
  7. 'Jane'  
  8. >>> class Some:  
  9.      __name = "Jane"  
  10.   
  11.       
  12. >>> she = Some()  
  13. >>> she.name  #这里不可以  
  14. Traceback (most recent call last):  
  15.   File "<pyshell#48>", line 1in <module>  
  16.     she.name  
  17. AttributeError: 'Some' object has no attribute 'name'  
  18. >>> she._Some__name #通过 _类名__方法或特性名,我们又可以访问它  
  19. 'Jane'  
  20. >>> class C:  
  21.     def __test(self):  
  22.         print('in C...')  
  23.     def call(self):  
  24.         self.__test() #类内访问私有方法和特性  
  25.   
  26.           
  27. >>> c = C()  
  28. >>> c.call()  
  29. in C...  

所以,你不可能完全限制其他人无法访问到你的类中方法和特性,所以,Python 并不能实现完全的封装


继承:
将其他类名写在class语句后的圆括号内就表示继承于某类
class 类名(基类名)
   语句块

[python] view plaincopyprint?
  1. >>> class A:  
  2.     def printA(self):  
  3.         print("in A...")  
  4.   
  5.           
  6. >>> class B(A):  
  7.     def printB(self):  
  8.         print('in B...')  
  9.   
  10.           
  11. >>> issubclass(A,B) #A不是B的子类  
  12. False  
  13. >>> issubclass(B,A) #B是A的子类  
  14. True  
  15. >>> B.__bases__  #B的基类  
  16. (<class '__main__.A'>,)  
  17. >>> b = B()  
  18. >>> isinstance(b,B)  #询问b是否是B的实例  
  19. True  
  20. >>> b.printA() #访问A中的方法  
  21. in A...  

多继承:
多继承的方法很容易,把几个类名写在一起就行了


class 类名(基类名1,基类名2,基类名3)
   语句块

子类中同名的方法会覆盖基类的方法,方法的调用跟继承的顺序有关,即方法在子类中未找到时,从左到右查找父类中是否包含方法

看下面的例子:

[python] view plaincopyprint?
  1. >>> class A:  
  2.     def test(self):  
  3.         print("in A...")  
  4.   
  5.           
  6. >>> class B(A):  
  7.     def test(self):  
  8.         print('in B...')  
  9.   
  10.           
  11. >>> class C(A):  
  12.     def test(self):  
  13.         print('in C...')  
  14.   
  15.           
  16. >>> class D(B,C):  
  17.     def test(self):  
  18.         print('in D...')  
  19.   
  20.           
  21. >>> d = D()  
  22. >>> d.test() #如果子类拥有该方法,那直接调用该方法  
  23. in D...  
  24. >>> class D(B,C): #重定义类D  
  25.     pass  
  26.   
  27. >>> d = D()  
  28. >>> d.test() #B先继承,在B中首先找到该方法,调用B的方法  
  29. in B...  
  30. >>> class D(C,B): #再次重定义,改变了继承顺序  
  31.     pass  
  32.   
  33. >>> d = D()  
  34. >>> d.test() #这次调用了C的方法  
  35. in C...  
  36. >>>   

当然,如果D、B、C都没有该方法,而A有,那么自然是调用A的方法


[python] view plaincopyprint?
  1. >>> hasattr(d,'test'#对象d是否有test方法  
  2. True  
  3. >>> hasattr(d,'next'#对象d是否有next方法  
  4. False  
  5. >>> hasattr(d.test,'__call__'#询问d的test方法是否可调用  
  6. True  


Python类的“构造函数” __init()__

将类实例化时,会创建一个空的类实例,一般的 Python 类的定义中会有一个特殊的方法来初始化,这个方法就是__init__(),当调用了类的实例化方法后,__init__()方法会立刻被这个类的实例调用。所以,__init__()不是构造函数,而是一个普通的方法.

[python] view plaincopyprint?
  1. >>> class A:  
  2.     count = 0;  
  3.     def __init__(self):  
  4.         A.count += 1  #每次调用该方法 count 自增 1  
  5.     def output(self):  
  6.         print(self.count)  
  7.   
  8.           
  9. >>> a1 = A()   
  10. >>> a1.output()  
  11. 1  
  12. >>> a2 = A()   
  13. >>> a2.output()  
  14. 2  
  15. >>> class A:  
  16.     def __init__(self,name):  
  17.         self.name = name  
  18.   
  19.           
  20. >>> a = A('Jane')  


Python 还有一个类似于“析构函数”的方法 __del__,但不建议使用,Python 的内存管理是用引用计数的,但引用数为0时销毁对象,但你很难确定什么时候 Python 会调用 del 方法,所以避免莫名其妙的错误的最好方法是不要使用它,将所有你要del做的事情写在一个主动调用的方法,然后自己进行管理

再说说Python的类属性和实例属性

类属性是属于一个类的变量,就像是C++中类的静态成员变量,你只需将该属性定义在所有方法的作用域外,即为类属性,但一般是紧跟在类名后面,类属性为所有实例所共有,你可以通过 类名.属性 来调用类属性
[python] view plaincopyprint?
  1. >>> class A:  
  2.     count = 0#这就是类属性  
  3.     def __init__(self):  
  4.         A.count += 1  #每次调用该方法 count 自增 1  
  5.     def output(self):  
  6.         print(self.count)  
  7.   
  8. >>> a1 = A()  
  9. >>> a1.output()  
  10. 1  
  11. >>> A.count = 0  
  12. >>> A.count  
  13. 0  
  14. >>> a1.output()  
  15. 0  


实例属性是属于实例自己的属性,你可以在任何方法中添加新的实例属性,甚至在类外添加,Python会在实例属性初次使用时,创建该属性并赋值

[python] view plaincopyprint?
  1. >>> class A:  
  2.     def __init__(self):  
  3.         self.num = 1  #添加实例属性num  
  4.     def again(self,name):  
  5.         self.name = name #添加实例属性name  
  6.   
  7.           
  8. >>> a1 = A()  
  9. >>> a1.num  
  10. 1  
  11. >>> a1.name #这时实例 a1 中还没有实例属性 name  
  12. Traceback (most recent call last):  
  13.   File "<pyshell#38>", line 1in <module>  
  14.     a1.name #这时实例 a1 中还没有实例属性 name  
  15. AttributeError: 'A' object has no attribute 'name'  
  16. >>> a1.again('Jane')  
  17. >>> a1.name #现在有了...  
  18. 'Jane'  
  19. >>> a1.call = '123456' #添加a1的实例属性 call  
  20. >>> a1.call  
  21. '123456'  


继续看下面的例子:

[python] view plaincopyprint?
  1. >>> class A:  
  2.     count = 0  
  3.     def __init__(self):  
  4.         A.count += 1  
  5.     def output(self):  
  6.         print(self.count)  
  7.   
  8.           
  9. >>> a1 = A()  
  10. >>> a2 = A()  
  11. >>> a3 = A()  
  12. >>> A.count # A的类属性count这时为3  
  13. 3  
  14. >>> A.count = 2 #更改A的类属性为2  
  15. >>> a1.count,a2.count, a3.count, A.count #A的所有实例的count也同样改变  
  16. (2222)  
  17. >>> a1.count = 5 #通过A的一个实例a1更改count  
  18. >>> a1.count, a2.count, a3.count, A.count #只有a1的count发生改变  
  19. (5222)  
  20. >>> A.count = 4 #再次更改A的类属性为4  
  21. >>> a1.count, a2.count, a3.count, A.count  #这时a1的count还是保持为5  
  22. (5444)    

通过上面的例子我们可以看到,类属性为所有实例和类所共有,通过 类名.类属性 可以更改类属性,并且所有实例的类属性也随之改变,但通过 实例名.类属性 来改变类属性,该实例的该类属性会变为实例属性,而不影响其他实例的类属性,以后通过 类名.类属性 来更改类属性,也不会影响到该实例的这个属性了,因为它变为实例属性啦。(好吧,我承认有点晕o(╯□╰)o)

0 0