zoukankan      html  css  js  c++  java
  • python之面向对象编程浅谈

    1.python中的类与对象

     1 Python中定义类的方式比较简单:
     2 
     3 class 类名:
     4 
     5 类变量
     6 
     7 def __init__(self,paramers):
     8 
     9 def 函数(self,...)
    10 
    11 …...
    12 
    13 其中直接定义在类体中的变量叫类变量,而在类的方法中定义的变量叫实例变量。类的属性包括成员变量和方法,其中方法的定义和普通函数的定义非常类似,但方法必须以self作为第一个参数。

    举例:

     1 >>>class MyFirstTestClass:
     2 
     3 class Spec="it is a test class"
     4 
     5 def__init__(self,word):
     6 
     7 print"say "+word
     8 
     9 def hello(self,name):
    10 
    11 print"hello "+name
    12 
    13  
    View Code

    在Python类中定义的方法通常有三种:实例方法,类方法以及静态方法。这三者之间的区别是实例方法一般都以self作为第一个参数,必须和具体的对象实例进行绑定才能访问,而类方法以cls作为第一个参数,cls表示类本身,定义时使用@classmethod;而静态方法不需要默认的任何参数,跟一般的普通函数类似.定义的时候使用@staticmethod

     1 >>>class MethodTest():
     2 
     3 count= 0
     4 
     5 defaddCount(self):
     6 
     7 MethodTest.count+=1
     8 
     9 print"I am an instance method,my count is"+str(MethodTest.count),self
    10 
    11 @staticmethod
    12 
    13 defstaticMethodAdd():
    14 
    15 MethodTest.count+=1
    16 
    17 print"I am a static methond,my count is"+str(MethodTest.count)
    18 
    19 @classmethod
    20 
    21 defclassMethodAdd(cls):
    22 
    23 MethodTest.count+=1
    24 
    25 print"I am a class method,my count is"+str(MethodTest.count),cls
    26 
    27  
    28 
    29 >>>
    30 
    31 >>>a=MethodTest()
    32 
    33 >>>a.addCount()
    34 
    35 Iam an instance method,my count is 1 <__main__.MethodTest instanceat 0x011EC990>
    36 
    37 >>>MethodTest.addCount()
    38 
    39  
    40 
    41 Traceback(most recent call last):
    42 
    43 File"<pyshell#5>", line 1, in <module>
    44 
    45 MethodTest.addCount()
    46 
    47 TypeError:unbound method addCount() must be called with MethodTest instance asfirst argument (got nothing instead)
    48 
    49 >>>a.staticMethodAdd()
    50 
    51 Iam a static methond,my count is2
    52 
    53 >>>MethodTest.staticMethodAdd()
    54 
    55 Iam a static methond,my count is3
    56 
    57 >>>a.classMethodAdd()
    58 
    59 Iam a class method,my count is4 __main__.MethodTest
    60 
    61 >>>MethodTest.classMethodAdd()
    62 
    63 Iam a class method,my count is5 __main__.MethodTest
    View Code

    从上面的例子来看,静态方法和类方法基本上区别不大,特别是有Java编程基础的人会简单的认为静态方法和类方法就是一回事,可是在Python中事实是这样的吗?看下面的例子:

     1 >>>MethodTest.classMethodAdd()
     2 
     3 Iam a class method,my count is5 __main__.MethodTest
     4 
     5 >>>class subMethodTest(MethodTest):
     6 
     7 pass
     8 
     9 >>>b=subMethodTest()
    10 
    11 >>>b.staticMethodAdd()
    12 
    13 Iam a static methond,my count is6
    14 
    15 >>>b.classMethodAdd()
    16 
    17 Iam a class method,my count is7 __main__.subMethodTest
    18 
    19 >>>a.classMethodAdd()
    20 
    21 Iam a class method,my count is8 __main__.MethodTest
    22 
    23 >>>
    View Code

    如果父类中定义有静态方法a(),在子类中没有覆盖该方法的话,Sub.a()仍然指的是父类的a()方法。而如果a()是类方法的情况下,Sub.a()指向的是子类。@staticmethod只适用于不想定义全局函数的情况。

    2.python的封装

    面向对象程序设计中的术语对象(Object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。传统意义上的“程序=数据结构+算法”被封装”掩盖“并简化为“程序=对象+消息”。对象是类的实例,类的抽象则需要经过封装。封装可以让调用者不用关心对象是如何构建的而直接进行使用。

    一个简单的Python类封装如下:

     1 _metaclass_=type # 确定使用新式类
     2 class Animal:
     3 
     4     def __init__(self): #构造方法 一个对象创建后会立即调用此方法
     5         self.Name="Doraemon"
     6         print self.Name
     7       
     8     def accessibleMethod(self): #绑定方法 对外公开
     9         print "I have a self! current name is:"
    10         print self.Name
    11         print "the secret message is:"
    12         self.__inaccessible()
    13         
    14     def __inaccessible(self): #私有方法 对外不公开 以双下划线开头
    15         print "U cannot see me..."
    16 
    17     @staticmethod
    18     def staticMethod():
    19         #self.accessibleMethod() #在静态方法中无法直接调用实例方法 直接抛出异常
    20         print "this is a static method"
    21 
    22     def setName(self,name): #访问器函数
    23         self.Name=name
    24 
    25     def getName(self): #访问器函数
    26         return self.Name
    27 
    28     name=property(getName,setName) #属性 可读可写
    View Code
    构造函数和析构函数
    
    Python的构造函数有两种,__init__和__new__,__init__的调用不会返回任何值,在继承关系中,为了保证父类实例正确的初始化,最好显示的调用父类的__init__方法。与__init__不同,__new__实际是个类方法,以cls作为第一个参数。
    
    如果类中同时定义了__init__和__new__方法,则在创建对象的时候会优先使用__new__.
    
    class A(object):
    
    def __init__(self):
    
    print("in init")
    
    def __new__(self):
    
    print("in new")
    
     
    A()
    
    如果__new__需要返回对象,则会默认调用__init__方法。利用new创建一个类的对象的最常用的方法为:super(currentclass,cls).__new__(cls[, ...])
    
    class A(object):
    
    def __new__(cls):
    
    Object = super(A,cls).__new__(cls)
    
    print "in New"
    
    return Object
    
    def __init__(self):
    
    print "in init"
    
     
    class B(A):
    
    def __init__(self):
    
    print "in B's init"
    
     
    
    B()
    
    __new__构造函数会可变类的定制的时候非常有用,后面的小节中会体现。
    
    Python由于具有垃圾回收机制,通常不需要用户显示的去调用析构函数,即使调用,实例也不会立即释放,而是到该实例对象所有的引用都被清除掉后才会执行。
    
    >>>class P:
    
    def__del__(self):
    
    print"deleted"
    
     
    
     
    
    >>>class S(P):
    
    def__init__(self):
    
    print'initialized'
    
    def__del__(self):
    
    P.__del__(self)
    
    print"child deleted"
    
     
    
     
    
    >>>a=S()
    
    initialized
    
    >>>b=a
    
    >>>c=a
    
    >>>id(a),id(b),id(c)
    
    (18765704,18765704, 18765704)
    
    >>>del a
    
    >>>del b
    
    >>>del c
    
    deleted
    
    childdeleted
    
    >>>
    
     

    3. Python中的继承

    Python同时支持单继承与多继承,继承的基本语法为class新类名(父类1,父类2,..,当只有一个父类时为单继承,当存在多个父类时为多继承。子类会继承父类的所有的属性和方法,子类也可以覆盖父类同名的变量和方法。在传统类中,如果子类和父类中同名的方法或者属性,在查找的时候基本遵循自左到右,深度优先的原则。如下列:

     1 >>>class A:
     2 
     3 defsayhi(self):
     4 
     5 print'I am A hi'
     6 
     7 >>>class B:
     8 
     9 defsayhi(self):
    10 
    11 print'I am B Hi'
    12 
    13 
    14 
    15 >>>class C(A,B):
    16 
    17 pass
    18 
    19 >>>d=C()
    20 
    21 >>>d.sayhi()
    22 
    23 Iam A hi
    24 
    25 >>>B.sayhi(d)
    26 
    27 Iam B Hi
    View Code

     单继承

     1 _metaclass_=type # 确定使用新式类
     2 class Animal:
     3 
     4     def __init__(self): 
     5         self.Name="Animal"
     6       
     7     def move(self,meters):
     8         print "%s moved %sm." %(self.Name,meters) 
     9         
    10 class Cat(Animal): #Cat是Animal的子类
    11 
    12      def __init__(self):  #重写超类的构造方法
    13         self.Name="Garfield"
    14 
    15 ##     def move(self,meters): #重写超类的绑定方法
    16 ##        print "Garfield never moves more than 1m."
    17 
    18 class RobotCat(Animal):
    19 
    20     def __init__(self):  #重写超类的构造方法
    21         self.Name="Doraemon"
    22 
    23 ##     def move(self,meters): #重写超类的绑定方法
    24 ##        print "Doraemon is flying."
    25 
    26 obj=Animal()
    27 obj.move(10) #输出:Animal moved 10m.
    28 
    29 cat=Cat()
    30 cat.move(1) #输出:Garfield moved 1m.
    31 
    32 robot=RobotCat()
    33 robot.move(1000) #输出:Doraemon moved 1000m.
    View Code

    多重继承

     1 class Animal:
     2   
     3     def eat(self,food):
     4         print "eat %s" %food 
     5         
     6 class Robot:
     7       
     8     def fly(self,kilometers):
     9         print "flyed %skm." %kilometers 
    10         
    11 class RobotCat(Animal,Robot): #继承自多个超类
    12 
    13     def __init__(self):  
    14         self.Name="Doraemon"
    15 
    16 robot=RobotCat() # 一只可以吃东西的会飞行的叫哆啦A梦的机器猫
    17 print robot.Name
    18 
    19 robot.eat("cookies") #从动物继承而来的eat
    20 
    21 robot.fly(10000000) #从机器继承而来的fly
    View Code

    需要注意的地方,即如果一个方法从多个超类继承,那么务必要小心继承的超类(或者基类)的顺序:

     1 class Animal:
     2   
     3     def eat(self,food):
     4         print "eat %s" %food
     5 
     6     def move(self,kilometers): #动物的move方法
     7         pass
     8         
     9 class Robot:
    10       
    11     def move(self,kilometers): #机器的move方法
    12         print "flyed %skm." %kilometers 
    13         
    14 class RobotCat(Animal,Robot): #继承自多个超类 如方法名称相同,注意继承的顺序
    15 #class RobotCat(Robot,Animal): 
    16     def __init__(self):  
    17         self.Name="Doraemon"
    18 
    19 robot=RobotCat() # 一只可以吃东西的会飞行的叫哆啦A梦的机器猫
    20 print robot.Name
    21 
    22 robot.eat("cookies") #从动物继承而来的eat
    23 
    24 robot.move(10000000) #本来是要从机器继承move方法,但是因为继承的顺序,这个方法直接继承自动物而pass掉
    View Code
    关于继承的构造函数:
    
    1.如果子类没有定义自己的构造函数,父类的构造函数会被默认调用,但是此时如果要实例化子类的对象,则只能传入父类的构造函数对应的参数,否则会出错
    
    classAddrBookEntry(object):
    
    'addressbook entry class'
    
    def__init__(self, nm, ph):
    
    self.name= nm
    
    self.phone= ph
    
    print'Created instance for:', self.name
    
    defupdatePhone(self, newph):
    
    self.phone = newph
    
    print'Updated phone# for:', self.name
    
      
    
    classEmplAddrBookEntry(AddrBookEntry):
    
    'EmployeeAddress Book Entry class'
    
    defupdateEmail(self, newem):
    
    self.email= newem
    
    print'Updated e-mail address for:', self.name
    
     
    
    john= EmplAddrBookEntry('John Doe', '408-555-1212')
    
    printjohn.name
    
     2.如果子类定义了自己的构造函数,而没有显示调用父类的构造函数,则父类的属性不会被初始化
    
    classAddrBookEntry(object):
    
    'addressbook entry class'
    
    def__init__(self, nm, ph):
    
    self.name= nm
    
    self.phone= ph
    
    print'Created instance for:', self.name
    
    defupdatePhone(self, newph):
    
    self.phone = newph
    
    print'Updated phone# for:', self.name
    
     
    
     
    
    classEmplAddrBookEntry(AddrBookEntry):
    
    'EmployeeAddress Book Entry class'
    
    def__init__(self, nm, ph, id, em):
    
    #AddrBookEntry.__init__(self, nm,ph)
    
    self.empid= id
    
    self.email= em
    
     
    
    defupdateEmail(self, newem):
    
    self.email= newem
    
    print'Updated e-mail address for:', self.name
    
     
    
    john= EmplAddrBookEntry('John Doe', '408-555-1212',42, 'john@spam.doe')
    
    printjohn.email
    
    printjohn.empid
    
     
    
    输出:
    
    john@spam.doe
    
    42
    
    Traceback(most recent call last):
    
     
    
    printjohn.name
    
    AttributeError:'EmplAddrBookEntry' object has no attribute 'name'
    
    
    
    3.如果子类定义了自己的构造函数,显示调用父类,子类和父类的属性都会被初始化
    
     
    
    classAddrBookEntry(object):
    
    'addressbook entry class'
    
    def__init__(self, nm, ph):
    
    self.name= nm
    
    self.phone= ph
    
    print'Created instance for:', self.name
    
    defupdatePhone(self, newph):
    
    self.phone = newph
    
    print'Updated phone# for:', self.name
    
     
    
     
    
    classEmplAddrBookEntry(AddrBookEntry):
    
    'EmployeeAddress Book Entry class'
    
    def__init__(self, nm, ph, id, em):
    
    AddrBookEntry.__init__(self, nm,ph)
    
    self.empid= id
    
    self.email= em
    
     
    
    defupdateEmail(self, newem):
    
    self.email= newem
    
    print'Updated e-mail address for:', self.name
    
     
    
    john= EmplAddrBookEntry('John Doe', '408-555-1212',42, 'john@spam.doe')
    
    printjohn.email
    
    printjohn.empid
    
    printjohn.name
    

    4.python的多态

     1 class calculator:
     2     def count(self, args):
     3         return 1
     4 
     5 
     6 calc = calculator()  # 自定义类型
     7 
     8 from random import choice
     9 
    10 obj = choice(['hello,world', [1, 2, 3], calc])  # obj是随机返回的 类型不确定
    11 print (type(obj))
    12 print(obj.count('a'))# 方法多态
    View Code


    对于一个临时对象obj,它通过Python的随机函数取出来,不知道具体类型(是字符串、元组还是自定义类型),都可以调用count方法进行计算,至于count由谁(哪种类型)去做怎么去实现我们并不关心。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 class Duck:
     4     def quack(self):
     5         print("Quaaaaaack!")
     6 
     7     def feathers(self):
     8         print("The duck has white and gray feathers.")
     9 
    10 
    11 class Person:
    12     def quack(self):
    13         print("The person imitates a duck.")
    14 
    15     def feathers(self):
    16         print("The person takes a feather from the ground and shows it.")
    17 
    18 
    19 def in_the_forest(duck):
    20     duck.quack()
    21     duck.feathers()
    22 
    23 
    24 def game():
    25     donald = Duck()
    26     john = Person()
    27     in_the_forest(donald)
    28     in_the_forest(john)
    29 
    30 
    31 game()
    View Code

    就in_the_forest函数而言,参数对象是一个鸭子类型和person类型,它实现了两个类型的相同名称的方法,打印的内容不一样,只是因为

    下面是运算符号(方法)的多态

    1 def add(x,y):
    2     return x+y
    3 
    4 print add(1,2) #输出3
    5 
    6 print add("hello,","world") #输出hello,world
    7 
    8 print add(1,"abc") #抛出异常 TypeError: unsupported operand type(s) for +: 'int' and 'str'
    View Code

     

     

  • 相关阅读:
    day10
    python学习第六天
    Python学习第五天
    python学习第四天第一部分
    python学习第三天第一部分
    python学习第二天第二部分
    python学习第二天第一部分
    崔西凡JavaWeb笔记day13-day15(2016年8月30日22:36:30)
    崔希凡JavaWeb笔记day10~day12(2016年8月22日11:55:20)
    崔希凡-javaWeb-笔记day07-day09(2016年7月26日23:14:40)
  • 原文地址:https://www.cnblogs.com/wspcoding/p/5699049.html
Copyright © 2011-2022 走看看