1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
一、什么事面向对象,以及面向对象的优点?
面向过程优缺点:
我们知道面向过程是流水线式的编程,过程就是解决问题的步骤,把大的问题化解成小的模块
面向过程优点: 极大的降低了程序的复杂度
面向过程缺点: 牵一发而动全身, 所以完成一个模块很少改动,否则改动的地方比较多
 
面向对象优缺点:
面向对象编程的核心是对象,由属性和函数构成
面向对象优点: 解决程序的扩展性,对某个类的修改能反映到整个体系中
 
类的语法结构:
class  类名:
     类体
     
例子:
class  People:
     language  =  'Chinese'
     def  func( self ):     #self把对象自身传进去
         pass
 
p1  =  People
p2  =  People
print (p1.language)
print (p2.language)
p1.language  =  'english'
print (p1.language)     #输出english
print (p2.language)     #输出english
 
注: 所有对象共用类的属性,所以p2也输出english
 
初始化类__init__
例子:
class  Garen:
     camp = 'Demacia'
     def  __init__( self ,nickname, aggressivity = 58 ,life_value = 456 ):
         self .nickname  =  nickname
         self .aggressivity  =  aggressivity
         self .life_value  =  life_value
         
     def  attack( self ,enemy):
         enemy.life_value  - =  self .aggressivity
hero  =  Garen( 'garen' 100 600 )     #加括号初始化类对象
print ( isinstance (hero, Garen))     #isinstance判断hero是否是类Garen的实例,是则返回True,否则返回False
print (Garen.__name__)    #类的名称
print (Garen.__doc__)     #类的文档字符串
print (Garen.__base__)    #类的第一个父类
print (Garen.__bases__)   #类的所有父类构成的元组
print (Garen.__dict__)    #类的字典属性
print (Garen.__module__)  #类定义所在的模块
print (Garen.__class__)   #实例对应的类
 
将函数绑定到对象上叫做对象的方法,并且会把自身传递给函数作为第一个参数
 
对象的交互:
class  Riven:
     camp  =  'Noxus'
     def  __init__( self , nickname, aggressivity = 54 ,life_value = 300 ):
         self .nickname  =  nickname
         self .aggressivity  =  aggressivity
         self .life_value  =  life_value
 
     def  attack( self ,enemy):
         enemy.life_value  - =  self .aggressivity
 
r1  =  Riven( '瑞问问' )
 
print (hero.life_value)
r1.attack(hero)
print (hero.life_value)
print ( id (r1.attack))     #id打印函数位置
print ( id (Riven.attack))
 
类有两种属性:数据属性和函数属性,数据属性共享给所有对象。
方法是绑定到所有对象上的,并且对象会传递给函数
创建对象就是创建了一个命名空间,对象会先找自己的命名空间,再找类的命名空间
 
 
 
二、继承
继承是一种创建新类的方式
继承的好处,减少代码冗余,
子类覆盖父类的方法叫做派生
 
例子:
class  ParentClass1:
     pass
 
class  ParentClass2:
     pass
 
class  SubClass1(ParentClass1):
     pass
class  SubClass2(ParentClass1,ParentClass2):
     pass
 
print (SubClass1.__bases__)     #打印父类
print (SubClass2.__bases__)     #打印父类
 
 
继承关系如图:

wKioL1k-G0_SHNl-AAAJmTcVCpM090.png-wh_50

F->A->E-B->D->C


wKiom1k-G4SxnRj8AAAIIhjY_sM050.png-wh_50

F->D->B-E->C->H->A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
派生类
例子:
class  Animal:
     def  __init__( self ,name,age,sex):
         self .name  =  name
         self .age  =  age
         self .sex  =  sex
 
     def  eat( self ):
         print ( 'eating' )
 
     def  talk( self ):
         print ( '%s 正在叫'  % self .name)
 
class  People(Animal):
     def  __init__( self ,name,age,sex,education):
         Animal.__init__( self ,name,age,sex)
         self .education  =  education
 
     def  talk( self ):
         Animal.talk( self )
         print ( '%s say hello'  % self .name)
 
class  Pig(Animal):
     pass
 
class  Dog(Animal):
     pass
 
peo1  =  People( 'hyh' , 20 , 'male' , '小学毕业' )
pig1  =  Pig( 'zhangsan' 16 'male' )
dog1  =  Dog( 'lisi' 16 'female' )
peo1.talk()
pig1.talk()
dog1.talk()
print ( isinstance (peo1, People))     #判断peo1是否是People类,返回True或False
print ( isinstance (pig1, Pig))         #继承反映的什么是什么的关系
print ( isinstance (dog1, Dog))
通过__dict__获取属性
class  Sub:
     def  __init__( self ):
         self .bar  =  123
     def  bar( self ):
         print ( 'Sub.bar' )
 
=  Sub()
print (s.__dict__)
print (s.__dict__[ 'bar' ])
 
组合: 在一个类中,以另外一个类的对象作为数据属性,称为类的组合,组合反映的是什么有什么的关系,
例子:
class  People:
     def  __init__( self ,name,age,sex):
         self .name = name
         self .age = age
         self .sex = sex
class  Date:
     def  __init__( self ,year,mon,day):
         self .year  =  year
         self .mon  =  mon
         self .day  =  day
 
     def  tell( self ):
         print ( '%s-%s-%s'  % ( self .year, self .mon, self .day))
 
class  Teacher(People):
     def  __init__( self ,name,age,sex,salary,year,mon,day):
         self .name  =  name
         self .age  =  age
         self .sex  =  sex
         self .salary  =  salary
         self .birth  =  Date(year,mon,day)
 
class  Student(People):
     def  __init__( self ,name,age,sex,year,mon,day):
         self .name = name
         self .age = age
         self .sex = sex
         self .birth = Date(year,mon,day)
 
t = Teacher( 'egon' , 18 , 'male' , 3000 , 1995 , 12 , 31 )
t.birth.tell()
 
 
定义类模拟接口
例子:
class  File :
     def  read( self ):
         raise  TypeError( '类型错误' )
 
     def  write( self ):
         raise  TypeError( '类型错误' )
 
class  Txt( File ):
     def  read( self ):
         print ( '文本数据的读取方法' )
 
     def  write( self ):
         print ( '文本数据的读取方法' )
 
class  Sata( File ):
     def  read( self ):
         print ( '硬盘数据的读取方法' )
 
     def  wirte( self ):
         print ( '硬盘数据的读取方法' )
 
class  Process( File ):
     def  read( self ):
         print ( '进程数据的读取方法' )
 
     def  write( self ):
         print ( '进程数据的读取方法' )
 
=  Process()
p.read()
=  Txt()
=  Sata()
print ( isinstance (p, Process))
print ( isinstance (t, Txt))
print ( isinstance (d, Sata))
 
注:  File 类定义功能函数,Txt,Sata,Process分别定义实现函数的方法
 
调用父类用 super 方法
例子:
class  Foo1:
     def  test( self ):
         print ( "from foo1.test" )
 
class  Foo2:
     def  test( self ):
         print ( 'from foo2.test' )
 
class  Bar(Foo1,Foo2):
     def  test( self ):
         super ().test()
         print ( 'Bar' )
=  Bar()
b.test()
1
三、封装
1
2
封装:主要为了保护数据的隐私,而把数据隐藏起来,只能通过接口去访问
类中通过__双下划线来隐藏数据属性和函数属性,含有__x的属性都会变成_类名__x的形式:
1
2
3
Foo:
     __x  =  __test():   ()
(Foo.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
封装实例:
class  People:
     __country  =  'China'
     
def  __init__( self ,name,age,sex):
     self .__name  =  name  
#self._People__name = name
    self .__age  =  age
     self .__sex  =  sex
     
def  tell_info( self ):
     print ( '人的名字是:%s, 人的年龄是: %s, 人的性别是: %s'  % ( self .__name,  self .__age,  self .__sex))
=  People( 'alex' 29 'male' )
print (p.__dict__)
p.tell_info()
 
注: 封装只在定义时检查语法
p.__x  =  1
print (p.__x)     #打印1
 
修改属性接口
class  People:
     def  __init__( self ,name,age):
         self .__name  =  name
         self .__age  =  age
 
     def  tell_info( self ):
         print ( '人的名字是: %s, 人的年龄是: %s'  % ( self .__name,  self .__age))
 
     def  set_info( self ,x, y):
         if  not  isinstance (x,  str ):
             raise  TypeError( '名字必须是字符串' )
         if  not  isinstance (y,  int ):
             raise  TypeError( '年龄必须是整数' )
 
         self .__name  =  x
         self .__age  =  y
 
=  People( 'alex' 20 )
p.tell_info()
p.set_info( 'hyh' 18 )
p.tell_info()
 
四、特性
property 是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
例子:
class  People:    
     def  __init__( self ,name,weight,height):
         self .name = name
         self .weight = weight
         self .height = height
     @ property    
     def  bmi( self ):        
         return  self .weight  /  ( self .height * * 2 )
 
p1 = People( 'egon' , 75 , 1.85 )
print (p1.bmi)
 
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是
执行了一个函数然后计算出来的,这种特性的使用方式遵循统一访问原则
 
五、绑定方法与非绑定方法
类中定义的函数分成两大类:
 
  一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):
 
     1.  绑定到类的方法:用 classmethod 装饰器装饰的方法。
 
                 为类量身定制
 
                 类.boud_method(),自动将类当作第一个参数传入
 
               (其实对象也可调用,但仍将类当作第一个参数传入)
 
     2.  绑定到对象的方法:没有被任何装饰器装饰的方法。
 
                为对象量身定制
 
                对象.boud_method(),自动将对象当作第一个参数传入
 
              (属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)
 
  二:非绑定方法:用 staticmethod 装饰器装饰的方法
 
      1.  不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已
 
    注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,
         对象调用该方法会自动传值,而 staticmethod 装饰的方法,不管谁来调用,都没有自动传值一说。
         
        例子:
        import  hashlib
        import  time
        class  MySQL:    
            def  __init__( self ,host,port):
                 self . id = self .create_id()
                 self .host = host
                 self .port = port
            @ staticmethod    
            def  create_id():  #就是一个普通工具
                 m = hashlib.md5( str (time.clock()).encode( 'utf-8' ))        
                 return  m.hexdigest()
        print (MySQL.create_id)  #<function MySQL.create_id at 0x0000000001E6B9D8> #查看结果为普通函数
        conn = MySQL( '127.0.0.1' , 3306 )
        print (conn.create_id)  #<function MySQL.create_id at 0x00000000026FB9D8> #查看结果为普通函数
        
        classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个
        参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数 classmethod 来把类中的函数定义成类方法
        
        例子:
        settings.py文件内容
        HOST = '127.0.0.1'
        PORT = 3306
        
        import  settings
        import  hashlib
        import  time
        class  MySQL:    
            def  __init__( self ,host,port):
                self .host = host
                self .port = port
 
            @ classmethod    
            def  from_conf( cls ):        
                print ( cls )        
                return  cls (settings.HOST,settings.PORT)
        print (MySQL.from_conf)  #<bound method MySQL.from_conf of <class '__main__.MySQL'>>
        conn = MySQL.from_conf() print (conn.host,conn.port)
        conn.from_conf()  #对象也可以调用,但是默认传的第一个参数仍然是类





     本文转自小白的希望 51CTO博客,原文链接:http://blog.51cto.com/haoyonghui/1934677 ,如需转载请自行联系原作者