目录
1 概述
2 类和实例
2.1 基本概念
2.2 访问限制
2.3 获取对象信息
2.4 小结
3 继承和多态
3.1 继承
3.2 多态
4 类方法和静态方法
4.1 类方法
4.2 静态方法
5 定制类和魔法方法
5.1 new
5.2 str & repr
7. >>> print Foo('ethan') # 使用 print
5.3 iter
5.4 getitem
5.5 getattr
5.6 call
5.7 小结
6 slots 魔法
7 使用 @property
8 你不知道的 super
8.1 深入 super()
8.2 MRO 列表
8.3 super 原理
8.4 陌生的 metaclass
8.5 熟悉又陌生的 type
8.6 最简单的情况
8.7 继承的情况
9 元类
9.1 概念
9.2 元类的使用
9.3 小结
Python 是一门面向对象编程( Object Oriented Programming, OOP )的语言,这里的对象可以。看做是由数据(或者说特性)以及一系列可以存取、操作这些数据的方法所组成的集合。面向对象编程。主要有以下特点:多态( Polymorphism ):不同类( Class )的对象对同一消息会做出不同的响应。封装( Encapsulation ):对外部世界隐藏对象的工作细节。继承( Inheritance ):以已有的类(父类)为基础建立专门的类对象。在 Python 中,元组、列表和字典等数据类型是对象,函数也是对象。那么,我们能创建自己的对象吗?答案是肯定的。跟其他 OOP 语言类似,我们使用类来自定义对象。本章主要介绍以下几个方面:
1. class Animal ( object ):2. pass
1. >>> animal = Animal () # 创建一个实例对象2. >>> animal3. < __main__ . Animal at 0x1030a44d0 >
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . name = name
1. >>> animal = Aniaml ( 'dog1' ) # 传入参数 'dog1'2. >>> animal . name # 访问对象的 name 属性3. 'dog1'
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . name = name4. def greet ( self ):5. print 'Hello, I am %s.' % self . name
1. >>> dog1 = Animal ( 'dog1' )2. >>> dog1 . name3. 'dog1'4. >>> dog1 . greet ()5. Hello , I am dog1 .
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . __name = name4. def greet ( self ):5.print 'Hello, I am %s.' % self . __name1. >>> dog1 = Animal ( 'dog1' )2. >>> dog1 . __name # 访问不了3. ---------------------------------------------------------------------------4. AttributeError Traceback ( most recent call last )5. < ipython - input - 206 - 7f6730db631e > in < module >()6. ----> 1 dog1 . __name7.8. AttributeError : 'Animal' object has no attribute '__name'9. >>> dog1 . greet () # 可以访问10. Hello , I am dog1 .
1. >>> a = 1232. >>> type ( a )3. int4. >>> b = '123'5. >>> type ( b )6. str
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . name = name4. def greet ( self ):5. print 'Hello, I am %s.' % self . name
1. >>> dog1 = Animal ( 'dog1' )2. >>> type ( dog1 )3. __main__ . Animal
1. >>> isinstance ( dog1 , Animal )2. True
1. >>> hasattr ( dog1 , 'name' )2. True3. >>> hasattr ( dog1 , 'x' )4. False5. >>> hasattr ( dog1 , 'greet' )6. True7. >>> getattr ( dog1 , 'name' )8. 'dog1'9. >>> getattr ( dog1 , 'greet' )10. < bound method Animal . greet of < __main__ . Animal object at 0x10c3564d0 >>11. >>> getattr ( dog1 , 'x' )12. ---------------------------------------------------------------------------13. AttributeError Traceback ( most recent call last )14. < ipython - input - 241 - 42f5b7da1012 > in < module >()15. ----> 1 getattr ( dog1 , 'x' )16.17. AttributeError : 'Animal' object has no attribute 'x'18. >>> getattr ( dog1 , 'x' , 'xvalue' )19. 'xvalue'20. >>> setattr ( dog1 , 'age' , 12 )21. >>> dog1 . age22. 12
1. >>> dir ( dog1 )2. [ '__class__' ,3. '__delattr__' ,4. '__dict__' ,5. '__doc__' ,6. '__format__' ,7. '__getattribute__' ,8. '__hash__' ,9. '__init__' ,10. '__module__' ,11. '__new__' ,12. '__reduce__' ,13. '__reduce_ex__' ,14. '__repr__' ,15. '__setattr__' ,16. '__sizeof__' ,17. '__str__' ,18. '__subclasshook__' ,19. '__weakref__' ,20. 'age' ,21. 'greet' ,22. 'name' ]
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . name = name4. def greet ( self ):5. print 'Hello, I am %s.' % self . name
1. class Dog ( object ):2. def __init__ ( self , name ):3. self . name = name4. def greet ( self ):5. print 'WangWang.., I am %s. ' % self . name
1. class Dog ( Animal ):2. def greet ( self ):3. print 'WangWang.., I am %s. ' % self . name
1. >>> animal = Animal ( 'animal' ) # 创建 animal 实例2. >>> animal . greet ()3. Hello , I am animal .4. >>>5. >>> dog = Dog ( 'dog' ) # 创建 dog 实例6. >>> dog . greet ()7. WangWang .., I am dog .
1. class Dog ( Animal ):2. def greet ( self ):3. print 'WangWang.., I am %s. ' % self . name4. def run ( self ):5. print 'I am running.I am running'
1. >>> dog = Dog ( 'dog' )2. >>> dog . greet ()3. WangWang .., I am dog .4. >>> dog . run ()5. I am running
1. >>> 1 + 22. 33. >>> 'a' + 'b'4. 'ab'
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . name = name4. def greet ( self ):5. print 'Hello, I am %s.' % self . name6.7. class Dog ( Animal ):8. def greet ( self ):9. print 'WangWang.., I am %s.' % self . name10.11. class Cat ( Animal ):12. def greet ( self ):13. print 'MiaoMiao.., I am %s' % self . name14.15. def hello ( animal ):16. animal . greet ()
1. >>> dog = Dog ( 'dog' )2. >>> hello ( dog )3. WangWang .., I am dog .4. >>>5. >>> cat = Cat ( 'cat' )6. >>> hello ( cat )7. MiaoMiao .., I am cat
1. class A ( object ):2. def foo ( self ):3. print 'Hello ' , self4.5. >>> a = A ()6. >>> a . foo ()7. Hello , < __main__ . A object at 0x10c37a450 >
1. class A ( object ):2. bar = 13. @classmethod4. def class_foo ( cls ):5. print 'Hello, ' , cls6. print cls . bar7.8. >>> A . class_foo () # 直接通过类来调用方法9. Hello , < class '__main__.A' >10. 1
1. class A ( object ):2. bar = 13. @staticmethod4. def static_foo ():5. print 'Hello, ' , A . bar6.7. >>> a = A ()8. >>> a . static_foo ()9. Hello , 110. >>> A . static_foo ()11. Hello , 1
__new____str__ , __repr____iter____getitem__ , __setitem__ , __delitem____getattr__ , __setattr__ , __delattr____call__
1. class A ( object ):2. _dict = dict ()3.4. def __new__ ( cls ):5. if 'key' in A . _dict :6. print "EXISTS"7. return A . _dict [ 'key' ]8. else :9. print "NEW"10. return object . __new__ ( cls )11.12. def __init__ ( self ):13. print "INIT"14. A . _dict [ 'key' ] = self
1. >>> a1 = A ()2. NEW3. INIT4. >>> a2 = A ()5. EXISTS6. INIT7. >>> a3 = A ()8. EXISTS9. INIT
1. class Foo ( object ):2. def __init__ ( self , name ):3. self . name = name4.5. >>> print Foo ( 'ethan' )6. < __main__ . Foo object at 0x10c37aa50 >
1. class Foo ( object ):2. def __init__ ( self , name ):3. self . name = name4. def __str__ ( self ):5. return 'Foo object (name: %s)' % self . name6.7. >>> print Foo('ethan') # 使用 print
8. Foo object ( name : ethan )9. >>>10. >>> str ( Foo ( 'ethan' )) # 使用 str11. 'Foo object (name: ethan)'12. >>>13. >>> Foo ( 'ethan' ) # 直接显示14. < __main__ . Foo at 0x10c37a490 >
1. class Foo ( object ):2. def __init__ ( self , name ):3. self . name = name4. def __str__ ( self ):5. return 'Foo object (name: %s)' % self . name6. def __repr__ ( self ):7. return 'Foo object (name: %s)' % self . name8.9. >>> Foo ( 'ethan' )10. 'Foo object (name: ethan)'
1. class Foo ( object ):2. def __init__ ( self , name ):3. self . name = name4. def __str__ ( self ):5. return 'Foo object (name: %s)' % self . name6. __repr__ = __str__
1. class Fib ( object ):2. def __init__ ( self ):3. self . a , self . b = 0 , 14.5. def __iter__ ( self ): # 返回迭代器对象本身6. return self7.8. def next ( self ): # 返回容器下一个元素9. self . a , self . b = self . b , self . a + self . b10. return self . a11.12. >>> fib = Fib ()13. >>> for i in fib :14. ... if i > 10 :15. ... break16. ... print i17. ...18. 119. 120. 221. 322. 523. 8
1. class Fib ( object ):2. def __getitem__ ( self , n ):3. a , b = 1 , 14. for x in xrange ( n ):5. a , b = b , a + b6. return a7.8. >>> fib = Fib ()9. >>> fib [ 0 ], fib [ 1 ], fib [ 2 ], fib [ 3 ], fib [ 4 ], fib [ 5 ]10. ( 1 , 1 , 2 , 3 , 5 , 8 )
1. class Fib ( object ):2. def __getitem__ ( self , n ):3. if isinstance ( n , slice ): # 如果 n 是 slice 对象4. a , b = 1 , 15. start , stop = n . start , n . stop6. L = []7. for i in xrange ( stop ):8. if i >= start :9. L . append ( a )10. a , b = b , a + b11. return L12. if isinstance ( n , int ): # 如果 n 是 int 型13. a , b = 1 , 114. for i in xrange ( n ):15. a , b = b , a + b16. return a
1. >>> fib = Fib ()2. >>> fib [ 0 : 3 ]3. [ 1 , 1 , 2 ]4. >>> fib [ 2 : 6 ]5. [ 2 , 3 , 5 , 8 ]
1. class Point ( object ):2. def __init__ ( self ):3. self . coordinate = {}4.5. def __str__ ( self ):6. return "point(%s)" % self . coordinate7.8. def __getitem__ ( self , key ):9. return self . coordinate . get ( key )10.11. def __setitem__ ( self , key , value ):12. self . coordinate [ key ] = value13.14. def __delitem__ ( self , key ):15. del self . coordinate [ key ]16. print 'delete %s' % key17.18. def __len__ ( self ):19. return len ( self . coordinate )20.21. __repr__ = __str__
1. >>> p = Point ()2. >>> p [ 'x' ] = 2 # 对应于 p.__setitem__('x', 2)3. >>> p [ 'y' ] = 5 # 对应于 p.__setitem__('y', 5)4. >>> p # 对应于 __repr__5. point ({ 'y' : 5 , 'x' : 2 })6. >>> len ( p ) # 对应于 p.__len__7. 28. >>> p [ 'x' ] # 对应于 p.__getitem__('x')9. 210. >>> p [ 'y' ] # 对应于 p.__getitem__('y')11. 512. >>> del p [ 'x' ] # 对应于 p.__delitem__('x')13. delete x14. >>> p15. point ({ 'y' : 5 })16. >>> len ( p )17. 1
1. class Point ( object ):2. def __init__ ( self , x = 0 , y = 0 ):3. self . x = x4. self . y = y5.6. >>> p = Point ( 3 , 4 )7. >>> p . x , p . y8. ( 3 , 4 )9. >>> p . z10. ---------------------------------------------------------------------------11. AttributeError Traceback ( most recent call last )12. < ipython - input - 547 - 6dce4e43e15c > in < module >()13. ----> 1 p . z14.15. AttributeError : 'Point' object has no attribute 'z'
1. def __getattr__ ( self , attr ):2. if attr == 'z' :3. return 04. raise AttributeError ( "Point object has no attribute %s" % attr )
1. class Point ( object ):2. def __init__ ( self , x = 0 , y = 0 ):3. self . x = x4. self . y = y5.6. def __getattr__ ( self , attr ):7. if attr == 'z' :8. return 09. raise AttributeError ( "Point object has no attribute %s" % attr )10.11. def __setattr__ ( self , * args , ** kwargs ):12. print 'call func set attr (%s, %s)' % ( args , kwargs )13. return object . __setattr__ ( self , * args , ** kwargs )14.15. def __delattr__ ( self , * args , ** kwargs ):16. print 'call func del attr (%s, %s)' % ( args , kwargs )17. return object . __delattr__ ( self , * args , ** kwargs )18.19. >>> p = Point ( 3 , 4 )20. call func set attr (( 'x' , 3 ), {})21. call func set attr (( 'y' , 4 ), {})22. >>> p . z23. 024. >>> p . z = 725. call func set attr (( 'z' , 7 ), {})26. >>> p . z27. 728. >>> p . w29. Traceback ( most recent call last ):30. File "" , line 1 , in < module >31. File "" , line 8 , in __getattr__32. AttributeError : Point object has no attribute w33. >>> p . w = 834. call func set attr (( 'w' , 8 ), {})35. >>> p . w36. 837. >>> del p . w38. call func del attr (( 'w' ,), {})39. >>> p . __dict__40. { 'y' : 4 , 'x' : 3 , 'z' : 7 }
1. class Point ( object ):2. def __init__ ( self , x , y ):3. self . x , self . y = x , y4. def __call__ ( self , z ):5. return self . x + self . y + z
1. >>> p = Point ( 3 , 4 )2. >>> callable ( p ) # 使用 callable 判断对象是否能被调用3. True4. >>> p ( 6 ) # 传入参数,对实例进行调用,对应 p.__call__(6)5. 13 # 3+4+6
1. class Point ( object ):2. def __init__ ( self , x = 0 , y = 0 ):3. self . x = x4. self . y = y5.6. >>> p = Point ( 3 , 4 )7. >>> p . z = 5 # 绑定了一个新的属性8. >>> p . z9. 510. >>> p . __dict__11. { 'x' : 3 , 'y' : 4 , 'z' : 5 }
1. class Point ( object ):2. __slots__ = ( 'x' , 'y' ) # 只允许使用 x 和 y3.4. def __init__ ( self , x = 0 , y = 0 ):5. self . x = x6. self . y = y
1. >>> p = Point ( 3 , 4 )2. >>> p . z = 53. ---------------------------------------------------------------------------4. AttributeError Traceback ( most recent call last )5. < ipython - input - 648 - 625ed954d865 > in < module >()6. ----> 1 p . z = 57.8. AttributeError : 'Point' object has no attribute 'z'
1. class Exam ( object ):2. def __init__ ( self , score ):3. self . _score = score4.5. def get_score ( self ):6. return self . _score7.8. def set_score ( self , val ):9. if val < 0 :10. self . _score = 011. elif val > 100 :12. self . _score = 10013. else :14. self . _score = val15.16. >>> e = Exam ( 60 )17. >>> e . get_score ()18. 6019. >>> e . set_score ( 70 )20. >>> e . get_score ()21. 70
1. class Exam ( object ):2. def __init__ ( self , score ):3. self . _score = score4.5. @property6. def score ( self ):7. return self . _score8.9. @score . setter10. def score ( self , val ):11. if val < 0 :12. self . _score = 013. elif val > 100 :14. self . _score = 10015. else :16. self . _score = val17.18. >>> e = Exam ( 60 )19. >>> e . score20. 6021. >>> e . score = 9022. >>> e . score23. 9024. >>> e . score = 20025. >>> e . score26. 100
1. class Exam ( object ):2. def __init__ ( self , score ):3. self . _score = score4.5. @property6. def score ( self ):7. return self . _score8.9. >>> e = Exam ( 60 )10. >>> e . score11. 6012. >>> e . score = 200 # score 是只读属性,不能设置值13. ---------------------------------------------------------------------------14. AttributeError Traceback ( most recent call last )15. < ipython - input - 676 - b0515304f6e0 > in < module >()16. ----> 1 e . score = 20017.18. AttributeError : can 't set attribute
1. class Animal ( object ):2. def __init__ ( self , name ):3. self . name = name4. def greet ( self ):5. print 'Hello, I am %s.' % self . name6.7. class Dog ( Animal ):8. def greet ( self ):9. super ( Dog , self ). greet () # Python3 可使用 super().greet()10. print 'WangWang...'
1. >>> dog = Dog ( 'dog' )2. >>> dog . greet ()3. Hello , I am dog .4. WangWang ..
1. class Base ( object ):2. def __init__ ( self , a , b ):3. self . a = a4. self . b = b5.6. class A ( Base ):7. def __init__ ( self , a , b , c ):8.super ( A , self ). __init__ ( a , b ) # Python3 可使用 super().__init__(a, b)9. self . c = c
1. class Base ( object ):2. def __init__ ( self ):3. print "enter Base"4. print "leave Base"5.6. class A ( Base ):7. def __init__ ( self ):8. print "enter A"9. super ( A , self ). __init__ ()10. print "leave A"11.12. class B ( Base ):13. def __init__ ( self ):14. print "enter B"15. super ( B , self ). __init__ ()16. print "leave B"17.18. class C ( A , B ):19. def __init__ ( self ):20. print "enter C"21. super ( C , self ). __init__ ()22. print "leave C"
1. Base2. / \3. / \4. A B5. \ /6. \ /7. C
1. >>> c = C ()2. enter C3. enter A4. enter B5. enter Base6. leave Base7. leave B8. leave A9. leave C
1. >>> C . mro () # or C.__mro__ or C().__class__.mro()2. [ __main__ . C , __main__ . A , __main__ . B , __main__ . Base , object ]
1. def super ( cls , inst ):2. mro = inst . __class__ . mro ()3. return mro [ mro . index ( cls ) + 1 ]
1. super ( C , self ). __init__ ()
1. [ __main__ . C , __main__ . A , __main__ . B , __main__ . Base , object ]
1. super ( A , self ). __init__ ()
1. class Foo ( object ):2. foo = True3.4. class Bar ( object ):5. bar = True6.7. def echo ( cls ):8. print cls9.10. def select ( name ):11. if name == 'foo' :12. return Foo # 返回值是一个类13. if name == 'bar' :14. return Bar15.16. >>> echo ( Foo ) # 把类作为参数传递给函数 echo17. < class '__main__.Foo' >18. >>> cls = select ( 'foo' ) # 函数 select 的返回值是一个类,把它赋给变量 cls19. >>> cls20. __main__ . Foo
1. class Foo ( object ):2. Foo = True3.4. >>> type ( 10 )5. < type 'int' >6. >>> type ( 'hello' )7. < type 'str' >8. >>> type ( Foo ())9. < class '__main__.Foo' >10. >>> type ( Foo )11. < type 'type' >
type( 类名 , 父类的元组(针对继承的情况,可以为空),包含属性和方法的字典(名称和值) )
1. class Foo ( object ):2. pass
1. Foo = type ( 'Foo' , ( object , ), {}) # 使用 type 创建了一个类对象
1. >>> print Foo2. < class '__main__.Foo' >3. >>> print Foo ()4. < __main__ . Foo object at 0x10c34f250 >
1. class Foo ( object ):2. foo = True3. def greet ( self ):4. print 'hello world'5. print self . foo
1. def greet ( self ):2. print 'hello world'3. print self . foo4.5. Foo = type ( 'Foo' , ( object , ), { 'foo' : True , 'greet' : greet })
2. >>> f . foo3. True4. >>> f . greet5. < bound method Foo . greet of < __main__ . Foo object at 0x10c34f890 >>6. >>> f . greet ()7. hello world8. True
1. class Base ( object ):2. pass
1. class Foo ( Base ):2. foo = True
1. Foo = type ( 'Foo' , ( Base , ), { 'foo' : True })
1. class Foo ( object ):2. name = 'foo'3. def bar ( self ):4. print 'bar'
1. class PrefixMetaclass ( type ):2. def __new__ ( cls , name , bases , attrs ):3. # 给所有属性和方法前面加上前缀 my_4. _attrs = (( 'my_' + name , value ) for name , value in attrs . items ())5.6. _attrs = dict (( name , value ) for name , value in _attrs ) # 转化为字典7. _attrs [ 'echo' ] = lambda self , phrase : phrase # 增加了一个 echo 方法8.9. return type . __new__ ( cls , name , bases , _attrs ) # 返回创建后的类
1. class Foo ( object ):2. __metaclass__ = PrefixMetaclass3. name = 'foo'4. def bar ( self ):5. print 'bar'
1. class Foo ( metaclass = PrefixMetaclass ):2. name = 'foo'3. def bar ( self ):4. print 'bar'
1. >>> f = Foo ()2. >>> f . name # name 属性已经被改变3. ---------------------------------------------------------------------------4. AttributeError Traceback ( most recent call last )5. < ipython - input - 774 - 4511c8475833 > in < module >()6. ----> 1 f . name7.8. AttributeError : 'Foo' object has no attribute 'name'9. >>>10. >>> f . my_name11. 'foo'12. >>> f . my_bar ()13. bar14. >>> f . echo ( 'hello' )15. 'hello'
1. class PrefixMetaclass ( type ):2. def __new__ ( cls , name , bases , attrs ):3. # 给所有属性和方法前面加上前缀 my_4. _attrs = (( 'my_' + name , value ) for name , value in attrs . items ())5.6. _attrs = dict (( name , value ) for name , value in _attrs ) # 转化为字典7. _attrs [ 'echo' ] = lambda self , phrase : phrase # 增加了一个 echo 方法8.9. return type . __new__ ( cls , name , bases , _attrs )10.11. class Foo ( object ):12. __metaclass__ = PrefixMetaclass # 注意跟 Python3 的写法有所区别13. name = 'foo'14. def bar ( self ):15. print 'bar'16.17. class Bar ( Foo ):18. prop = 'bar'
1. >>> b = Bar ()2. >>> b . prop # 发现没这个属性3. ---------------------------------------------------------------------------4. AttributeError Traceback ( most recent call last )5. < ipython - input - 778 - 825e0b6563ea > in < module >()6. ----> 1 b . prop7.8. AttributeError : 'Bar' object has no attribute 'prop'9. >>> b . my_prop10. 'bar'11. >>> b . my_name12. 'foo'13. >>> b . my_bar ()14. bar15. >>> b . echo ( 'hello' )16. 'hello'