• 面向对象的概念及延伸


    概念

    Python使用类(class)和对象(object),进行面向对象(object-oriented programming,简称OOP)的编程。

    可以理解为对象(object)属性相近的东西,再进行归类(class)命名

    建立一个对象

    1 class name(object):      #定义名称为name的类,object为对象
    2      attribute1          #定义name类的属性1
    3      attribute2          #定义name类的属性2

    说明:

    1.对象为object命名为name的类class。

    2.括号中为object时,表示这个类为最大的父类(到顶了)。

    3.引用对象的属性为:object.attribute

    举例:

     1 #定义一个鸟类    
     2 class Bird(object):                    #定义了一个类别(class),就是鸟(Bird)
     3     have_feather = True                #属性1,有羽毛
     4     way_of_reproduction  = 'egg'       #属性2,产卵生殖方式
     5 
     6 summer = Bird()                        #summer为小鸡,使用前面定义的鸟类
     7 print summer.way_of_reproduction       #使用对象.属性调用
     8 
     9     
    10 #新增移动的方法-move
    11 class Bird(object):
    12     have_feather = True
    13     way_of_reproduction = 'egg'
    14     def move(self, dx, dy):            #类的内部定义move方法
    15         position = [0,0]               #注意是list,所以使用[]
    16         position[0] = position[0] + dx
    17         position[1] = position[1] + dy
    18         return position                #返回dx,dy移动的结果值
    19 summer = Bird()
    20 print 'after move:',summer.move(5,8)    
    21 summer.move(5,8)                       #回顾下函数,可以直接输出结果,同上一步
    22 
    23 
    24 #Chicken/Oriole继承Bird
    25 class Chicken(Bird):                   #新定义小鸡类,继承于Bird类
    26     way_of_move = 'walk'               #小鸡类属性1,移动方式
    27     possible_in_KFC = True             #小鸡类属性2,KFC是否存在
    28 
    29 class Oriole(Bird):                    #新定义黄鹂类,同样继承于Bird类
    30     way_of_move = 'fly'                #黄鹂类属性1,移动方式
    31     possible_in_KFC = False            #黄鹂类属性2,KFC是否存在
    32 
    33 summer = Chicken()                     #summer使用小鸡类,小鸡继承鸟类,summer具备鸟类的属性
    34 print summer.have_feather              #调用鸟类的属性1
    35 print summer.move(5,8)                 #调用鸟类的移动方法

     小结:

    1.有一只小鸡叫summer,它是个对象,且属于鸟类。我们使用开头定义的鸟类。

    2.summer = Bird()为创建对象,并说明summer是类别鸟中的一个对象,summer就有了鸟的类属性。对属性的引用是通过对象.属性(object.attribute)的形式实现。

    3.对于类的内部定义方法。区别与直接定义函数,它的参数中有一个self,它是为了方便我们引用对象自身,self代表了根据类定义而创建的对象。方法的第一个参数必须是self,无论是否用到

    4.类别可以细分为子类,子类可以通过继承(inheritance)获得父类的全部属性。

    5.类定义括号中写了(bird),说明了Chicken是属于鸟类(bird)的一个子类,即Chicken继承自Bird。Bird就是Chicken的父类,Chicken将享有Bird的所有属性

    类的内部定义方法延伸

    上面我们说到,对于类的内部定义方法第一个参数必须是self,我们实践一下。

    1 class Human(object):            #定义一个Human类
    2     laugh = 'hahahaha'          #属性laugh
    3     def show_laugh(self):       #定义show_laugh方法
    4         print self.laugh        #调用Human类属性并且输出
    5     def laugh_100th(self):      #定义laugh_100th方法
    6         for i in range(100):    #for循环100次
    7             self.show_laugh()   #调用show_laugh()方法
    8 li_lei = Human()                #li_lei为对象 
    9 li_lei.laugh_100th()            #输出laugh_100th()结果

    主要通过类和方法输出100次hahahaha。

    想去掉show_laugh方法,直接用laugh_100th去实现。

    实践一:

     1 class Human(object):
     2     laugh = 'hahahaha'
     3     def laugh_100th(self):
     4         for i in range(100):
     5             self.laugh()           #self.laugh()是错误的写法,实践二中会改正
     6 
     7             
     8 >>> meng = Human() 
     9 >>> print (meng.laugh_100th)       #输出错误,正确调用格式为meng.laugh_100th()
    10 <bound method Human.laugh_100th of <__main__.Human object at 0x0000000002E75B70>>
    11 >>> print (meng.laugh_100th())     #laugh_100th不可被调用
    12 
    13 Traceback (most recent call last):
    14   File "<pyshell#96>", line 1, in <module>
    15     print (meng.laugh_100th())
    16   File "<pyshell#93>", line 5, in laugh_100th
    17     self.laugh()
    18 TypeError: 'str' object is not callable
    19 class Human(object): 20 laugh = 'hahahaha' 21 def laugh_100th(self): 22 for i in range(100): 23 print self.laugh() #错误写法 24 25 26 >>> meng = Human() 27 >>> meng.laugh_100th() #错误调用 28 29 Traceback (most recent call last): 30 File "<pyshell#100>", line 1, in <module> 31 meng.laugh_100th() 32 File "<pyshell#98>", line 5, in laugh_100th 33 print self.laugh() 34 TypeError: 'str' object is not callable
    35 class Human(object): 36 laugh = 'hahahaha' 37 def laugh_100th(self): 38 for i in range(100): 39 self.laugh() 40 print self.laugh() #错误写法 41 42 43 >>> meng = Human() 44 >>> meng.laugh_100th() #错误调用 45 46 Traceback (most recent call last): 47 File "<pyshell#105>", line 1, in <module> 48 meng.laugh_100th() 49 File "<pyshell#103>", line 5, in laugh_100th 50 self.laugh() 51 TypeError: 'str' object is not callable

    分析:

    报错:TypeError: 'str' object is not callable

    字面意思为str不可被系统调用,就是正在调用一个不能被调用的变量或对象,具体表现就是你调用函数、变量的方式错误。

    laugh为类属性,正确调用为self.laugh而不是self.laugh()。

    实践二:

     1 class Human(object):
     2     laugh = 'hahahaha'
     3     def laugh_100th(self):
     4         for i in range(100):
     5             self.laugh               #调用Human类属性,self.laugh写法正确
     6 
     7             
     8 >>> li = Human()
     9 >>> print li.laugh_100th()           #函数无return值,并且内部无输出,返回结果为None
    10 None
    13 class Human(object): 14 laugh = 'hahahaha' 15 def laugh_100th(self): 16 for i in range(100): 17 self.laugh 18 print self.laugh #输出self.laugh值 19 20 21 >>> li = Human() 22 >>> li.laugh_100th() #输出一次结果值 23 hahahaha

    分析:

    在函数laugh_100th()中,for循环调用Human属性laugh,print在for循环的外层,输出时函数执行结束。

    实践三:

     1 class Human(object):
     2     laugh = 'hahahaha'
     3     def laugh_100th(self):
     4         for i in range(100):
     5             print self.laugh         #直接在for循环中输出结果
     6 
     7             
     8 >>> li = Human()
     9 >>> li.laugh_100th()                 #正确输出100次结果
    10 hahahaha
    11 hahahaha
    12 ...
    13 hahahaha
    14 hahahaha

    分析: 

    把print放在for循环内层直接输出结果,for循环并未停止,所以可以循环100次。

    直接li.laugh_100th() 调用,无None值返回。

    实践四:

     1 class Human(object):
     2     laugh = 'hahahaha'
     3     def laugh_100th(self):
     4         for i in range(100):
     5             return self.laugh        #把实践三的print修改为return
     6 
     7         
     8 >>> wang = Human()
     9 >>> print (wang.laugh_100th())       #输出一次结果值
    10 hahahaha
    11 class Human(object): 12 laugh = 'hahahaha' 13 def laugh_100th(self): 14 for i in range(100): 15 self.laugh 16 return #再修改为return放在外部 17 18 19 >>> wang = Human() 20 >>> print (wang.laugh_100th()) #return后无值,返回None 21 None 22 >>> wang.laugh_100th() #直接调用,无结果值 23 >>>

    分析:

    1.把实践三的print修改为return,只返回一次结果值。因为执行到return时,函数停止执行函数内余下的语句。(复习一下函数总结

    2.把return放在外部,又变成了return后无返回值的场景。输出结果为None。

    综上,正确输出为实践三。

    __init__方法

    __init__()是一个特殊方法(special method)。Python有一些特殊方法。Python会特殊的对待它们。特殊方法的特点是名字前后有两个下划线。

    如果你在类中定义了__init__()这个方法,创建对象时,Python会自动调用这个方法。这个过程也叫初始化。

    --大神总结的话少一句都不行。

    1 class happyBird(Bird):
    2     def __init__(self,more_words):     #self后面要有变量值
    3         print more_words               #输出more_words
    4 xiu = happyBird('ha') #输出格式,结果值为ha

    我们创建xiu对象,__init__()方法被自动调用。最后一行的语句(xiu= happyBird...)先创建了对象,然后执行:

    xiu.__init__(more_words)

    'ha' 被传递给了__init__()的参数more_words

    输出规范一点:

    1 class happyBird(Bird):
    2     def __init__(self,more_words):
    3         print 'We are happy birds.',more_words
    4 xin = happyBird('ha')      #We are happy birds. ha

    我们可以尝试用__init__方法输出实践中100次haha。

    这是实践三:

     1 class Human(object):
     2     laugh = 'hahahaha'
     3     def laugh_100th(self):
     4         for i in range(100):
     5             print self.laugh
     6 
     7             
     8 >>> li = Human()
     9 >>> li.laugh_100th()
    10 hahahaha
    11 hahahaha
    12 ...13 hahahaha

    __init__方法实现:

     1 class human(object):
     2     def __init__(self,laugh):   #定义laugh
     3         for i in range(100):
     4             print laugh         #输出laugh值
     5             
     6 li = human('haha')              #调用输出100次haha
     7 ha
     8 ha
     9 ...
    10 ha  

    对象的性质

    我们讲到了许多属性,但这些属性是类的属性。所有属于该类的对象会共享这些属性。比如说,鸟都有羽毛,鸡都不会飞。

    在一些情况下,我们定义对象的性质,用于记录该对象的特别信息。比如说,人这个类。性别是某个人的一个性质,不是所有的人类都是男,或者都是女。这个性质的值随着对象的不同而不同。李雷是人类的一个对象,性别是男;韩美美也是人类的一个对象,性别是女。

    当定义类的方法时,必须要传递一个self的参数。这个参数指代的就是类的一个对象。我们可以通过操纵self,来修改某个对象的性质。比如用类来新建一个对象,即下面例子中的li_lei, 那么li_lei就被self表示。我们通过赋值给self.attribute,给li_lei这一对象增加一些性质,比如说性别的男女。self会传递给各个方法。在方法内部,可以通过引用self.attribute,查询或修改对象的性质。

    这样,在类属性的之外,又给每个对象增添了各自特色的性质,从而能描述多样的世界。

    1 class Human(object):
    2     def __init__(self, input_gender):
    3         self.gender = input_gender      #self.attribute赋值
    4     def printGender(self):
    5         print self.gender               #调用self.attribute
    6  
    7 li_lei = Human('male')                  #这里,'male'作为参数传递给__init__()方法的input_gender变量
    8 print li_lei.gender
    9 li_lei.printGender()

    在初始化中,将参数input_gender,赋值给对象的性质,即self.gender

    li_lei拥有了对象性质gender。gender不是一个类属性。Python在建立了li_lei这一对象之后,使用li_lei.gender这一对象性质,专门储存属于对象li_lei的特有信息。

    对象的性质也可以被其它方法调用,调用方法与类属性的调用相似,正如在printGender()方法中的调用。

    其他:

    如果在语句7输入后,直接输出结果值的话,需要在语句3后加上print。如下。

    2 ...
    3         self.gender = input_gender    
    4         print self.gender            #输出结果值
    5     def printGender(self):
    6 ...

    因为我们在调用__init__时,函数中没有输出结果值。

    参考下列写法:

    1 class Human(object):           
    2     laugh = 'hahahaha'         
    3     def show_laugh(self):      
    4         print self.laugh       #调用Human类属性值并且输出
    5     def laugh_100th(self):     
    6         for i in range(100):   
    7             self.show_laugh()  #调用show_laugh方法
    8 li_lei = Human()               
    9 li_lei.laugh_100th()           

    本章小结:

    1.self可以调用类属性,格式为self.attribute;self也可以改变对象的性质,通过赋值给self.attribute实现。

    2.__init__()在建立对象时自动执行,self后必须带有变量值。

  • 相关阅读:
    Linux软件安装中RPM与YUM 区别和联系
    Linux分区类型EXT2、EXT3、EXT4详解
    【转】SQLServer数据库还原数据库后因孤立用户问题导致无法登陆的处理
    CVE-2018-8045 Joomla内核SQL注入漏洞
    SQL注入漏洞靶场-sqli-labs学习[1-10]
    SQL注入漏洞
    文件包含漏洞
    CSRF的攻击与防御
    XSS漏洞的基本原理
    Linux高性能服务器编程(一):TCP/IP协议族
  • 原文地址:https://www.cnblogs.com/shengyin/p/11236602.html
Copyright © 2020-2023  润新知